java - 从 Byte Buddy 0.7.7 迁移到 1.0.2 时遇到问题

标签 java bytecode instrumentation byte-buddy

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

相关文章:

java - 为什么数组中有多余的值?

java - 使用 GPS 坐标(经度、纬度)查找区域设置是什么?

java - 将参数传递给 bytebuddy 拦截器

java - 通过分析字节码,我如何检测 catch block 中的显式 throw 语句调用?

javascript - 重新定义window.console函数时保持原路径位置

java - Kotlin 接口(interface)可以缓存值吗?

java - 静态工厂 builder 的麻烦

java - 执行一段字节码

Java 仪器

javascript - 在 Javascript/jQuery 中包装一个函数