raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.31k stars 808 forks source link

Please help me check this issue. I use the inherited LaunchedURLClassLoader method in agentLauncher to load my lib package, and then inject the shared class into Bootstrap ClassLoader. #1703

Closed biuifuture closed 2 months ago

biuifuture commented 3 months ago

Caused by: java.lang.ClassNotFoundException: net.bytebuddy.matcher.MethodParameterTypeMatcher at java.net.URLClassLoader.findClass(URLClassLoader.java:387) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at com.xx.xx.xagent.loader.thirdlib.org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) at com.xx.xx.xagent.loader.AgentClassLoader.loadClass(AgentClassLoader.java:33) at java.lang.ClassLoader.loadClass(ClassLoader.java:351)

biuifuture commented 3 months ago

【xagent】: 13:19:54.592 ERROR [com.xx.xx.xagent.agent.AgentListener] - transformer com.xx.xx.xagent.plugins.methodgather.BeanTest error java.lang.NoClassDefFoundError: net/bytebuddy/matcher/MethodParameterTypeMatcher at net.bytebuddy.matcher.ElementMatchers.hasGenericType(ElementMatchers.java:246) at net.bytebuddy.matcher.ElementMatchers.hasType(ElementMatchers.java:235) at net.bytebuddy.dynamic.scaffold.MethodRegistry$Default.prepare(MethodRegistry.java:476) at net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder.toTypeWriter(RedefinitionDynamicTypeBuilder.java:203) at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter.make(DynamicType.java:4062) at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:12529) at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:12464) at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1800(AgentBuilder.java:12173) at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$LegacyVmDispatcher.run(AgentBuilder.java:12873) at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$LegacyVmDispatcher.run(AgentBuilder.java:12811) at java.security.AccessController.doPrivileged(Native Method) at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doPrivileged(AgentBuilder.java) at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:12373) at sun.instrument.TransformerManager.transform(TransformerManager.java:188) at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:756) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:473) at java.net.URLClassLoader.access$100(URLClassLoader.java:74) at java.net.URLClassLoader$1.run(URLClassLoader.java:369) at java.net.URLClassLoader$1.run(URLClassLoader.java:363) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:362) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at com.xx.xx.xagent.plugins.methodgather.MethodGatherPluginTest.main(MethodGatherPluginTest.java:7) Caused by: java.lang.ClassNotFoundException: net.bytebuddy.matcher.MethodParameterTypeMatcher at java.net.URLClassLoader.findClass(URLClassLoader.java:387) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at com.xx.xx.xagent.loader.thirdlib.org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) at com.xx.xx.xagent.loader.AgentClassLoader.loadClass(AgentClassLoader.java:33) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ... 28 more

biuifuture commented 3 months ago

@Advice.OnMethodEnter public static ContextInfo onEnter(@Advice.This Object self, @Advice.Origin("#t") String className, @Advice.Origin("#m") String method, @Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) { ContextInfo contextInfo = new ContextInfo(); Dispatcher.getAction("xxAction").onEnter(self,className,method,args,contextInfo); return contextInfo; }

@Advice.OnMethodExit(onThrowable = Throwable.class)
public static void onExit(@Advice.Enter ContextInfo contextInfo,
                          @Advice.This Object self,
                          @Advice.Origin("#t") String className,
                          @Advice.Origin("#m") String method,
                          @Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args,
                          @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object retValue,
                          @Advice.Thrown Throwable throwable) {
    Dispatcher.getAction("xxAction").onExit(self,className, method, args, retValue, throwable, contextInfo);
}
raphw commented 3 months ago

Is Byte Buddy on the class path from before? If so, you might have a version clash since the version used might differ from the version you are using.

biuifuture commented 3 months ago

【xagent】: 20:06:14.845 ERROR [com.xx.xx.xagent.agent.AgentListener] - transformer com.xx.xx.xagent.plugins.methodgather.BeanTest with classLoader sun.misc.Launcher$AppClassLoader@18b4aac2 error java.lang.VerifyError: (class: net/bytebuddy/dynamic/scaffold/TypeWriter$Default$ForInlining$WithFullProcessing, method: writeTo signature: (Lnet/bytebuddy/jar/asm/ClassVisitor;Lnet/bytebuddy/dynamic/scaffold/TypeInitializer;Lnet/bytebuddy/dynamic/scaffold/TypeWriter$Default$ForInlining$ContextRegistry;II)Lnet/bytebuddy/jar/asm/ClassVisitor;) Incompatible argument to function

biuifuture commented 3 months ago

There is only one version(1.14.18) of bytebuddy in the agent

biuifuture commented 3 months ago

Another error was reported in the listener:

【xagent】: 20:13:44.334 ERROR [com.xx.xx.xagent.agent.AgentListener] - transformer java.util.IdentityHashMap$KeyIterator with classLoader null error
java.lang.LinkageError: loader constraint violation: when resolving method "net.bytebuddy.pool.TypePool$Default$GenericTypeExtractor$IncompleteToken$ForInnerClass.<init>(Ljava/lang/String;Lnet/bytebuddy/pool/TypePool$Default$GenericTypeExtractor$IncompleteToken;)V" the class loader (instance of com/jdh/xfyl/xagent/loader/AgentClassLoader) of the current class, net/bytebuddy/pool/TypePool$Default$GenericTypeExtractor, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the method's defining class, net/bytebuddy/pool/TypePool$Default$GenericTypeExtractor$IncompleteToken$ForInnerClass, have different Class objects for the type net/bytebuddy/pool/TypePool$Default$GenericTypeExtractor$IncompleteToken used in the signature
    at net.bytebuddy.pool.TypePool$Default$GenericTypeExtractor.visitInnerClassType(TypePool.java:1878)

This is how it is configured in my agentBuilder

AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, module, protectionDomain) -> {
                addUserClassLoader(agentClassLoader,classLoader);
                return builder.visit(
                        Advice.to(transformerDefinition.getAgentAdvice().getClass()).on(transformerDefinition.getMethodMather())
                );
            };
            new AgentBuilder.Default()
                    .with(new AgentListener())
                    .with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
                    .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
                    .with(AgentBuilder.TypeStrategy.Default.REDEFINE)
.with(AgentBuilder.LocationStrategy.ForClassLoader.STRONG.withFallbackTo(ClassFileLocator.ForClassLoader.ofBootLoader()))
                    .ignore(ElementMatchers.isSynthetic())
                    .or(ElementMatchers.nameStartsWith("sun."))
                    .or(ElementMatchers.nameStartsWith("com.sun."))
                    .or(ElementMatchers.nameStartsWith("brave."))
                    .or(ElementMatchers.nameStartsWith("zipkin2."))
                    .or(ElementMatchers.nameStartsWith("com.fasterxml"))
                    .or(ElementMatchers.nameStartsWith("org.apache.logging"))
                    .or(ElementMatchers.nameStartsWith("kotlin."))
                    .or(ElementMatchers.nameStartsWith("javax."))
                    .or(ElementMatchers.nameStartsWith("net.bytebuddy."))
                    .or(ElementMatchers.nameStartsWith("com\\.sun\\.proxy\\.\\$Proxy.+"))
                    .or(ElementMatchers.nameStartsWith("java\\.lang\\.invoke\\.BoundMethodHandle\\$Species_L.+"))
                    .or(ElementMatchers.nameStartsWith("org.junit."))
                    .or(ElementMatchers.nameStartsWith("junit."))
                    .or(ElementMatchers.nameStartsWith("java.util."))
                    .or(ElementMatchers.nameStartsWith("com.intellij."))
                    .type(transformerDefinition.getClassMather())
                    .transform(transformer)
                    .installOn(instrumentation);
biuifuture commented 3 months ago

I seem to have found the root cause. In the agent's premise, I used LaunchedURLClassLoader to load bytebuddy, but I don't know why it was loaded by AppClassLoader。

public static void premain(String agentArgs, Instrumentation instrumentation) throws Exception {
        JarFileArchive archive = new JarFileArchive(getArchiveFileContains());
        URL[] urls = nestArchiveUrls(archive);
        ClassLoader agentClassLoader = new AgentClassLoader(urls);
        loadAgent(agentClassLoader,() -> {
            agentClassLoader.loadClass(AGENT_CLASS)
                    .getDeclaredMethod(AGENT_METHOD, String.class, Instrumentation.class)
                    .invoke(null, agentArgs, instrumentation);
            return null;
        });
    }

This is the jar directory structure I built

image