背景:
由于历史原因,我们有两个agent 用bytebuddy 对同一个类增强冲突报错:
net.bytebuddy.pool.TypePool$Resolution$NoSuchTypeException: Cannot resolve type description for xxx$auxiliary$NqnfNQKN
报错原因
解决方案:
new AgentBuilder
.Default(byteBuddy)
.with(AgentBuilder.LocationStrategy.ForClassLoader.WEAK)
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.<TypeDescription>nameStartsWith("com.demo"))
.transform(new AgentBuilder.Transformer() {
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
return builder
.constructor(ElementMatchers.<MethodDescription>any())
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration().to(new FirstAgentConstructInterceptor())));
}
})
.with(new Listener("firstAagent"))
.installOn(inst);
---------------------------------------------------------------------------------
public class Listener implements AgentBuilder.Listener {
private String agentName;
public Listener(String agentName) {
this.agentName = agentName;
}
public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded, DynamicType dynamicType) {
File debuggingClassesRootPath = new File("D:\\" + agentName + "\\");
if (!debuggingClassesRootPath.exists()) {
debuggingClassesRootPath.mkdirs();
}
try {
dynamicType.saveIn(debuggingClassesRootPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在第二个代理中,我创建了一个新的 locationStrategy 并使用第一个代理字节码路径:
public class ApmClassFileLocationStrategy implements AgentBuilder.LocationStrategy{
private final AgentBuilder.LocationStrategy defaultStrategy;
private final String dir;
public ApmClassFileLocationStrategy(AgentBuilder.LocationStrategy defaultStrategy, String dir) {
this.defaultStrategy = defaultStrategy;
this.dir = dir;
}
public static ApmClassFileLocationStrategy of(AgentBuilder.LocationStrategy defaultStrategy, String dir) {
return new ApmClassFileLocationStrategy(defaultStrategy, dir);
}
public ClassFileLocator classFileLocator(ClassLoader classLoader, JavaModule module) {
ClassFileLocator folderLocator = new ClassFileLocator.ForFolder(new File(dir));
return new ClassFileLocator.Compound(defaultStrategy.classFileLocator(classLoader, module), folderLocator);
}
}
---------------------------------------------------------------------------------
new AgentBuilder
.Default(byteBuddy)
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(new ApmClassFileLocationStrategy(AgentBuilder.LocationStrategy.ForClassLoader.WEAK, "D:\\firstAagent"))
.with(new ErrorLoggingListener())
.type(ElementMatchers.<TypeDescription>nameStartsWith("com.demo"))
.transform(new AgentBuilder.Transformer() {
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
return builder
.constructor(ElementMatchers.<MethodDescription>any())
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration().to(new SecondeAgentConstructInterceptor())));
}
})
.with(new Listener("secondAgent"))
.installOn(inst);
原因分析:
bytebuddy生成的代理类 xxx$auxiliary$NqnfNQKN 类的字节码信息并没有存放到磁盘中,而是在内存中。第一个egent 生成类的字节码并没有立即加载 。第二个类加载器在自己的加载路径中 找不到 xxx$auxiliary$NqnfNQKN 的字节码文件 ,就会报上面的错误 。