字节好友 - java.lang.IllegalStateException:无法解析“”的类型描述 - KafkaProducer

问题描述

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 命名空间。