Java 如何应用、删除和重新应用bytebuddy转换?

Java 如何应用、删除和重新应用bytebuddy转换?,java,byte-buddy,Java,Byte Buddy,我试图通过javaagent应用、删除和重新应用bytebuddy转换,如下代码所示。通过重置TableClassFileTransformer::reset可以正确地执行删除操作,但重新应用不起作用 //目标类 public@interface-ToString{ } 公共接口表{ 字符串say(最终字符串名); } @托斯特林 公共类Greeter实现Greetable{ 公共字符串say(最终字符串名){ 返回“Hello”+name; } } //注意,some转换来自示例 新代理bu

我试图通过javaagent应用、删除和重新应用bytebuddy转换,如下代码所示。通过重置TableClassFileTransformer::reset可以正确地执行删除操作,但重新应用不起作用

//目标类
public@interface-ToString{
}
公共接口表{
字符串say(最终字符串名);
}
@托斯特林
公共类Greeter实现Greetable{
公共字符串say(最终字符串名){
返回“Hello”+name;
}
}
//注意,some转换来自示例
新代理builder.Transformer(){
@凌驾
公共DynamicType.Builder转换(DynamicType.Builder,
类型描述类型描述,
类加载器类加载器,
JavaModule(模块){
返回builder.method(名为(“say”))
.截距(FixedValue.value(“转换”);
}
})
//转换
公共类MyProgram{
公共静态void main(最终字符串[]args){
ByteBuddyAgent.install();
AgentBuilder bldr=新建AgentBuilder.Default()。
使用(AgentBuilder.Listener)。
流线型写作。
toSystemOut())。
使用(重新定义策略)。
重译)。
disableClassFormatChanges()。
类型(IssubType of(
Greetable.class)。
transform();
ResettableClassFileTransformer重置器=
bldr.installOnByteBuddyAgent();
Greetable g1=新的问候者();
System.out.println(g1.say(“001”);
//删除转换
reset.reset(ByteBuddyAgent.getInstrumentation(),
重新定义策略(重新翻译);
Greetable g2=新的问候者();
System.out.println(g2.say(“002”);
//重新应用转换
bldr.installOn(ByteBuddyAgent.getInstrumentation());
Greetable g3=新的问候者();
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.
请您帮助建议如何实现重新申请

编辑1 我已将
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)
编辑2 我已经从接口更改了类型匹配器

type(isSubTypeOf(Greetable.class))
将类具体化为

type(isSubTypeOf(Greeter.class))

g3.say()
被转换为属性。接口匹配和转换是否有任何限制?

我可以从
AgentBuilder.Transformer
API看出,您正在运行一个旧版本的Byte Buddy。我刚刚尝试了一个最新的版本,效果很好

实际上,您是否依赖于
@ToString
注释来触发转换?转换尚未加载的类时,Byte Buddy会直接从类文件中读取注释。对于加载的类,它使用加载的表示。您的批注没有使用
@RetentionPolicy(Retention.RUNTIME)
进行批注以保持批注的可见性,这可能是问题所在


UPDATE:您需要通过
not(isastract())和(named(“say”)
say
方法从接口中排除,从而优化方法匹配器。否则,您将在重新传输尝试中包括该接口。JVM似乎在第二次重新传输中失败了,因为在类加载后,您无法将抽象方法更改为默认方法。通常,这会触发异常,但在您的情况下,虚拟机似乎会无声地抑制错误。

非常感谢您的回复。我已经将
byte buddy
更新为版本
1.6.11
,作为更新的问题。请您提供进一步的建议好吗?接下来,我将
类型匹配器
接口
更改为
具体类
,并将其用作更新的问题#2。有什么限制吗?