ByteBuddy - 在 java 代理中阅读 class 注释

ByteBuddy - Read class annotations in a java agent

我试图在使用 ByteBuddy 实现的 java 代理中应用一些转换之前访问 class 的注释。 为了访问注释,我试图加载 Class 对象,但似乎这会创建一个重复的 class 定义。

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.instrument.Instrumentation;

public class SimpleTestAgent {
    public static void premain(String arg, Instrumentation inst) {
        new AgentBuilder.Default()
                .type(ElementMatchers.isAnnotatedWith(SomeAnnotationType.class))
                .transform((builder, type, classLoader, javaModule) -> {
                    try {
                        Class loadedClass = Class.forName(type.getName(), true, classLoader);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                    return builder;
                })
                .installOn(inst);
    }
}

一个简单的 class 只是创建了一个 class 测试 Class 的实例,它用预期的注释进行了注释,抛出以下异常:

Exception in thread "main" java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "TestClass"

public class AgentTest {
    public static void  main (String[] args) {
        TestClass pet = new TestClass();
    }
}

我正在尝试像以下所述的示例中那样实施代理:Easily-Create-Java-Agents-with-ByteBuddy

有没有一种方法可以加载 Class 对象而不会导致这个问题,或者有一种方法可以使用传递给 transformation() 方法的参数来访问注释?

转换应该能够实现新接口,而不仅仅是覆盖方法,这就是为什么我认为我不能使用 "ForAdvice"。

更新 以下循环仅在 Class.forName() 执行后才找到 TestClass。这意味着 class 尚未加载,因此可能没有希望使用 Class.forName 来获取注释。

for (Class<?> t : inst.getAllLoadedClasses()) {
    System.out.println("Class name: " + t.getName());
}

可以使用传递给 transform() 方法的 net.bytebuddy.description.type.TypeDescription 实例获取有关 class 的注释和完整信息。

问题是,例如,我需要可以使用反射调用的方法对象。如果我能以某种方式访问​​正在转换的 class 的 Class 对象,那就更容易了。

Byte Buddy 已经通过 TypeDescription API 公开了有关 class 注释的所有信息,您不应将 classes 作为 class 加载在转换期间加载的在应用转换之前加载此 class 并中止 class 加载并出现您观察到的错误。相反,实现你自己的匹配器:

.type(type -> check(type.getDeclaredAnnotations().ofType(SomeAnnotation.class).load())

Byte Buddy 将在不加载载体 class 本身的情况下为您呈现注释,而是使用其自己的 class 文件处理器来呈现注释。

您应该确保在安装您的代理生成器之前加载注释 class 以避免此确切注释的循环。