我在测试套件中遇到了一些问题,从 Byte Buddy 0.7.7 迁移到 1.0.2
这是一个简化的例子:
public class ReproBug {
@Test
public void test() {
ByteBuddyAgent.install();
new AgentBuilder.Default().type(nameStartsWith("test"))
.transform(new AgentBuilder.Transformer() {
@Override
public Builder<?> transform(Builder<?> builder, TypeDescription typeDescription) {
return builder.method(isDeclaredBy(typeDescription)).intercept(to(new Object() {
@RuntimeType
public void intercept(@SuperCall Callable<?> zuper, @Origin Method method) {
System.out.println("intercepting " + method.getName());
}
}));
}
}).installOnByteBuddyAgent();
MyClass.staticMethod();
}
}
MyClass
的代码:
class MyClass {
public static void staticMethod() {
System.out.println("in staticMethod");
}
}
Byte Buddy 0.7.7 没有报告任何错误,但是在 1.0.2 中我得到了类似 Cannot resolve type description for test.MyClass$auxiliary$dUGbkato
的错误。
完整日志(来自 AgentBuilder.Listener): http://pastebin.com/ytsQR5bi
注意方法被拦截了。
但是在我的一些测试中,我得到了双倍的拦截量,因为它拦截了辅助类的方法 call
。
最佳答案
我在添加监听器时能够重现您的问题。 0.7.7 和 1.0.3 的区别在于字节好友加载辅助类的时间。在 1.0.3 中,Byte Buddy 加载一个类作为类静态初始化器的一部分。这样,Byte Buddy 确保没有辅助类会触发检测类的过早加载,例如,如果辅助类是检测类的子类型。在过去,这会中止检测,而 Byte Buddy 会因错误而失败。
这意味着,辅助类不再作为检测过程的一部分加载,并向代理 API 发出类加载事件,以便转换器激活。由于您的匹配器包括所有带有测试的类型,并且由于辅助类型与其检测类型位于同一包中,因此尝试检测这些辅助类型但找不到类文件。因此,引发了异常。
在 Byte Buddy 1.1.0(即将发布)中,构建器 API 中有一个新方法,ignoreTypes
,其中可以指定应完全忽略的任何类型。默认情况下,Byte Buddy 现在将忽略任何合成类型。由于辅助类型是合成的,您遇到的问题不再发生在默认设置中。
实际上,日志中的信息对您的程序没有任何影响。原始类型始终按预期进行检测。只有当 Byte Buddy 实际上可以在重复检测发生的地方检测您的辅助类型时,才会出现问题。
一般来说,在单元测试中,您应该始终确保在注册代理后删除转换器,例如:
Instrumentation inst = ByteBuddyAgent.install();
ClassFileTransformer cft = agentBuilder.installOnByteBuddyAgent();
try {
// run test
finally {
inst.removeTransformer(cft);
}
在测试中非常具体地说明您想要拦截的类也是一种很好的做法,例如通过指定类的完全限定名称。
关于java - 从 Byte Buddy 0.7.7 迁移到 1.0.2 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34925309/