我正在尝试通过javaagent apply, remove and re-apply
进行bytebuddy转换,如下面的代码所示。删除通过ResettableClassFileTransformer::reset
正常工作,但重新申请无效。
// The target classes
public @interface ToString {
}
public interface Greetable {
String say(final String name);
}
@ToString
public class Greeter implements Greetable {
public String say(final String name) {
return "Hello " + name;
}
}
//note the some transform is from the example
new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder transform(DynamicType.Builder builder,
TypeDescription typeDescription,
ClassLoader classloader,
JavaModule module) {
return builder.method(named("say"))
.intercept(FixedValue.value("transformed");
}
})
// The transformation
public class MyProgram {
public static void main(final String[] args) {
ByteBuddyAgent.install();
AgentBuilder bldr = new AgentBuilder.Default().
with(AgentBuilder.Listener.
StreamWriting.
toSystemOut()).
with(RedefinitionStrategy.
RETRANSFORMATION).
disableClassFormatChanges().
type(isSubTypeOf(
Greetable.class)).
transform(<some transform>);
ResettableClassFileTransformer resetter =
bldr.installOnByteBuddyAgent();
Greetable g1 = new Greeter();
System.out.println(g1.say("001"));
//remove the transformation
resetter.reset(ByteBuddyAgent.getInstrumentation(),
RedefinitionStrategy.RETRANSFORMATION);
Greetable g2 = new Greeter();
System.out.println(g2.say("002"));
//re-apply the transformation
bldr.installOn(ByteBuddyAgent.getInstrumentation());
Greetable g3 = new Greeter();
System.out.println(g3.say("003"));
}
}
输出
TRANSFORM Greetable [sun.misc.Launcher$AppClassLoader@7ab2bfe1,
null,
loaded=true]
TRANSFORM Greeter [sun.misc.Launcher$AppClassLoader@7ab2bfe1,
null,
loaded=true]
transformed //note: the g1.say() is transformed.
Hello 002 //note: the g2 is an orginal
TRANSFORM Greetable [sun.misc.Launcher$AppClassLoader@7ab2bfe1,
null,
loaded=true]
TRANSFORM Greeter [sun.misc.Launcher$AppClassLoader@7ab2bfe1,
null,
loaded=true]
Hello 003 //note the re-apply has not worked.
请您帮忙建议如何重新申请?
我已将byte-buddy
更新为版本1.6.11
并更改了AgentBuilder.Transformer
。结果仍然相同。 g3.say()
未被转换。
我的环境是
Windows 10 64Bits
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
我已从界面
更改了类型匹配器type(isSubTypeOf(Greetable.class))
到具体类
type(isSubTypeOf(Greeter.class))
g3.say()
正在转变。接口匹配和转换是否有任何限制?
答案 0 :(得分:1)
我正在使用AgentBuilder.Transformer
API运行旧版Byte Buddy。我刚刚尝试使用最新版本,但它确实有效。
实际上,您是否依靠@ToString
注释来触发转换?当您转换尚未加载的类时,Byte Buddy直接从类文件中读取注释。对于加载的类,它使用加载的表示。您的注释未使用@RetentionPolicy(Retention.RUNTIME)
进行注释,以保留可能存在问题的注释可见性。
更新:您需要通过say
从界面中排除not(isAbstract()).and(named("say"))
方法来优化方法匹配器。否则,您在重新转换尝试中包含接口。由于在加载类之后无法将抽象方法更改为默认方法,因此JVM似乎默默地无法进行第二次重新转换。通常情况下,这会触发异常,但在您的情况下,VM似乎会默默地抑制错误。