运行 从 Byte Buddy 0.7.7 迁移到 1.0.2 的问题

Running into issues migrating from Byte Buddy 0.7.7 to 1.0.2

我 运行 在我的测试套件中遇到了一些问题,从 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的区别在于字节好友加载辅助的时间class。在 1.0.3 中,Byte Buddy 加载了一个 class 作为 class 的静态初始化器的一部分。这样,Byte Buddy 确保没有辅助 class 触发检测 class 的过早加载,例如,如果辅助 class 是检测 class 的子类型.在过去,这会中止检测,而 Byte Buddy 会因错误而失败。

暗示,辅助 classes 不再作为检测过程的一部分加载,并向代理 API 发出 class 加载事件,这样转换器就可以获取积极的。由于您的匹配器包括所有带有测试的类型,并且由于辅助类型与其检测类型位于同一包中,因此尝试检测这些辅助类型但找不到 class 文件。所以抛出异常。

在 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);
}

在测试中非常具体地说明您要拦截的 class 内容也是一种很好的做法,例如通过指定 class 的完全限定名称。