我在测试套件中遇到了一些问题,从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");
}
}
字节好友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之间的差异是Byte Buddy加载辅助类的时间。在1.0.3中,字节伙伴将类加载为类的静态初始化程序的一部分。这样,Byte Buddy可以确保没有辅助类触发已检测类的过早加载,例如,如果辅助类是已检测类的子类型。过去,这已中止了检测,并且Byte Buddy会因错误而失败。
这意味着,辅助类不再作为检测过程的一部分加载,并向代理API发出类加载事件,以使转换器处于活动状态。由于您的匹配器包括受测试的所有类型,并且由于辅助类型与其检测类型在同一包中找到,因此尝试检测这些辅助类型但找不到类文件。因此,提出了例外。
在Byte Buddy 1.1.0(即将发布)中,构建器API中有一个新方法ignoreTypes
,其中可以指定应完全忽略的任何类型。默认情况下,字节好友现在将忽略任何合成类型。由于辅助类型是合成类型,因此在默认设置中不会再出现您遇到的问题。
实际上,日志中的信息对您的程序没有任何影响。原始类型始终按预期进行检测。仅当Byte Buddy实际上可以在发生重复检测的情况下检测您的辅助类型时,才会出现问题。
一般而言,在单元测试中,应始终确保在注册代理后要删除变压器,例如:
Instrumentation inst = ByteBuddyAgent.install();
ClassFileTransformer cft = agentBuilder.installOnByteBuddyAgent();
try {
// run test
finally {
inst.removeTransformer(cft);
}
在测试中非常具体地指定您要拦截哪些类也是一个好习惯,例如通过指定类的完全限定名称。