我在测试套件中遇到了一些问题,从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);
}


在测试中非常具体地指定您要拦截哪些类也是一个好习惯,例如通过指定类的完全限定名称。

09-06 07:07