问题描述
Byte Buddy 拦截 KafkaProducer.send() 抛出以下异常:
[Byte Buddy] ERROR org.apache.kafka.clients.producer.KafkaProducer [null,null,Thread[main,5,main],loaded=false]
java.lang.IllegalStateException: Cannot resolve type description for org.apache.kafka.clients.producer.Producer
at net.bytebuddy.pool.TypePool$Resolution$Illegal.resolve(TypePool.java:159)
at net.bytebuddy.pool.TypePool$Default$WithLazyResolution$LazyTypeDescription.delegate(TypePool.java:973)
at net.bytebuddy.description.type.TypeDescription$AbstractBase$OfSimpleType$WithDelegation.getEnclosingType(TypeDescription.java:8360)
at net.bytebuddy.pool.TypePool$Default$LazyTypeDescription$GenericTypetoken$ForParameterizedType$LazyParameterizedType.getownerType(TypePool.java:5222)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor.onParameterizedType(TypeDescription.java:1857)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForDetachment.onParameterizedType(TypeDescription.java:2032)
at net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType.accept(TypeDescription.java:5168)
at net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection.accept(TypeDescription.java:6320)
at net.bytebuddy.description.type.TypeList$Generic$AbstractBase.accept(TypeList.java:291)
at net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default$1.represent(InstrumentedType.java:414)
at net.bytebuddy.ByteBuddy.rebase(ByteBuddy.java:888)
at net.bytebuddy.agent.builder.AgentBuilder$Typestrategy$Default$1.builder(AgentBuilder.java:2526)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:11116)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:11063)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1600(AgentBuilder.java:10805)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$LegacyVmdispatcher.run(AgentBuilder.java:11455)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$LegacyVmdispatcher.run(AgentBuilder.java:11402)
at java.security.AccessController.doPrivileged(Native Method)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10970)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
at java.lang.classLoader.findBootstrapClass(Native Method)
at java.lang.classLoader.findBootstrapClassOrNull(ClassLoader.java:1008)
at java.lang.classLoader.loadClass(ClassLoader.java:407)
at java.lang.classLoader.loadClass(ClassLoader.java:405)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.classLoader.loadClass(ClassLoader.java:351)
这是我的 Agent Premain 方法:
public static void premain(String agentArgs,Instrumentation inst) {
try {
final File bootstrapFolder;
try {
bootstrapFolder = Files.createTempDirectory("agent-bootstrap").toFile();
} catch (Exception e) {
e.printstacktrace(System.err);
return;
}
new AgentBuilder.Default()
.ignore(nameStartsWith("sun."))
.with(AgentBuilder.Listener.StreamWriting.toSystemOut())
.with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
.with((AgentBuilder.LocationStrategy) (classLoader,module) -> new ClassFileLocator.Compound(
ClassFileLocator.ForClassLoader.of(classLoader),ClassFileLocator.ForClassLoader.ofBootLoader()))
.with(new AgentBuilder.InjectionStrategy.UsingInstrumentation(inst,bootstrapFolder))
.type(named("org.apache.kafka.clients.producer.KafkaProducer"))
.transform((builder,typeDescription,classLoader,module) -> {
return builder
.method(named("send").and(takesArguments(1)))
.intercept(Advice.to(KafkaProducerInterceptor.class));
}
)
.installOn(inst);
} catch (Exception e) {
e.printstacktrace();
}
}
解决方法
日志行表明 KafkaProducer
是由引导加载程序加载的。生产者是否以某种方式附加到这个装载机上?附加类不提供它们的类文件作为资源并且不能通过正常方式定位。如果您有明确的位置,则可以在设置 ClassFileLocator
时将此位置添加为 LocationStrategy
。
设置 .ignore(nameStartsWith("sun."))
表示您打算在引导加载程序上检测类。如果是这种情况,您需要格外小心,最好还排除 net.bytebuddy
命名空间。