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了辅助类的方法。

4

1 回答 1

1

添加侦听器时,我能够重现您的问题。0.7.7 和 1.0.3 的区别在于 Byte Buddy 加载辅助类的时间。在 1.0.3 中,Byte Buddy 加载一个类作为类的静态初始化程序的一部分。这样,Byte Buddy 确保没有辅助类触发检测类的过早加载,例如,如果辅助类是检测类的子类型。在过去,这会中止检测,而 Byte Buddy 会因错误而失败。

作为暗示,辅助类不再作为检测过程的一部分加载,而是向代理 API 发出类加载事件,以便转换器激活。由于您的匹配器包含所有带有测试的类型,并且由于辅助类型与其检测类型位于同一包中,因此尝试检测这些辅助类型但找不到类文件。因此,引发了异常。

在 Byte Buddy 1.1.0(即将发布)中,builder API 中有一个新方法,ignoreTypes可以指定任何应该完全忽略的类型。默认情况下,Byte Buddy 现在将忽略任何合成类型。由于辅助类型是合成的,因此您遇到的问题在默认设置中不再发生。

但实际上,日志中的信息对您的程序没有任何影响。原始类型始终按照应有的方式进行检测。只有当 Byte Buddy 实际上可以在发生重复检测的地方检测您的辅助类型时,才会出现问题。

一般来说,在单元测试中,您应该始终确保在注册代理后删除转换器,例如:

Instrumentation inst = ByteBuddyAgent.install();
ClassFileTransformer cft = agentBuilder.installOnByteBuddyAgent();
try {
 // run test
finally {
  inst.removeTransformer(cft);
}

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

于 2016-01-22T12:31:51.520 回答