diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java index f4cda75569a57406ad926aca3f114608bdee6cf7..b28f1a79c048b2c4fe19072883619a88fae73cd7 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java @@ -1,8 +1,6 @@ package org.skywalking.apm.agent.core.plugin; import net.bytebuddy.dynamic.DynamicType; -import net.bytebuddy.pool.TypePool; -import net.bytebuddy.pool.TypePool.Resolution; import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine; import org.skywalking.apm.util.StringUtil; import org.skywalking.apm.logging.ILog; @@ -17,18 +15,16 @@ import org.skywalking.apm.logging.LogManager; public abstract class AbstractClassEnhancePluginDefine { private static final ILog logger = LogManager.getLogger(AbstractClassEnhancePluginDefine.class); - private TypePool classTypePool; - /** * Main entrance of enhancing the class. * * @param transformClassName target class. - * @param builder byte-buddy's builder to manipulate target class's bytecode. + * @param builder byte-buddy's builder to manipulate target class's bytecode. * @return the new builder, or null if not be enhanced. * @throws PluginException, when set builder failure. */ public DynamicType.Builder define(String transformClassName, - DynamicType.Builder builder) throws PluginException { + DynamicType.Builder builder, ClassLoader classLoader) throws PluginException { String interceptorDefineClassName = this.getClass().getName(); if (StringUtil.isEmpty(transformClassName)) { @@ -44,8 +40,7 @@ public abstract class AbstractClassEnhancePluginDefine { String[] witnessClasses = witnessClasses(); if (witnessClasses != null) { for (String witnessClass : witnessClasses) { - Resolution witnessClassResolution = classTypePool.describe(witnessClass); - if (!witnessClassResolution.isResolved()) { + if (!WitnessClassFinder.INSTANCE.exist(witnessClass, classLoader)) { logger.warn("enhance class {} by plugin {} is not working. Because witness class {} is not existed.", transformClassName, interceptorDefineClassName, witnessClass); return null; @@ -64,7 +59,7 @@ public abstract class AbstractClassEnhancePluginDefine { } protected abstract DynamicType.Builder enhance(String enhanceOriginClassName, - DynamicType.Builder newClassBuilder) throws PluginException; + DynamicType.Builder newClassBuilder) throws PluginException; /** * Define the classname of target class. @@ -86,8 +81,4 @@ public abstract class AbstractClassEnhancePluginDefine { protected String[] witnessClasses() { return new String[] {}; } - - public void setClassTypePool(TypePool classTypePool) { - this.classTypePool = classTypePool; - } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java index cad9fa8a137c4280435a87105287b51ccc241c12..d1b72047d63f246f155156a33e62675226226bf0 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java @@ -1,6 +1,5 @@ package org.skywalking.apm.agent.core.plugin; -import net.bytebuddy.pool.TypePool; import org.skywalking.apm.logging.ILog; import org.skywalking.apm.logging.LogManager; @@ -24,8 +23,6 @@ public class PluginBootstrap { * @return plugin definition list. */ public List loadPlugins() { - TypePool classTypePool = TypePool.Default.ofClassPath(); - PluginResourcesResolver resolver = new PluginResourcesResolver(); List resources = resolver.getResources(); @@ -50,7 +47,6 @@ public class PluginBootstrap { logger.debug("loading plugin class {}.", pluginDefine.getDefineClass()); AbstractClassEnhancePluginDefine plugin = (AbstractClassEnhancePluginDefine) Class.forName(pluginDefine.getDefineClass()).newInstance(); - plugin.setClassTypePool(classTypePool); plugins.add(plugin); } catch (Throwable t) { logger.error(t, "load plugin [{}] failure.", pluginDefine.getDefineClass()); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/TracingBootstrap.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/TracingBootstrap.java index 8ba5e4c3e1166145002807ee5f2078d4b0a95294..00e004a4ab953f58cbc75ecaec179e28ba5311e3 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/TracingBootstrap.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/TracingBootstrap.java @@ -30,7 +30,7 @@ public class TracingBootstrap { * Main entrance for testing. * * @param args includes target classname ( which exists "public static void main(String[] args)" ) and arguments - * list. + * list. * @throws PluginException * @throws ClassNotFoundException * @throws NoSuchMethodException @@ -62,7 +62,7 @@ public class TracingBootstrap { } DynamicType.Builder newClassBuilder = new ByteBuddy().rebase(resolution.resolve(), ClassFileLocator.ForClassLoader.ofClassPath()); - newClassBuilder = ((AbstractClassEnhancePluginDefine) plugin).define(enhanceClassName, newClassBuilder); + newClassBuilder = ((AbstractClassEnhancePluginDefine)plugin).define(enhanceClassName, newClassBuilder, TracingBootstrap.class.getClassLoader()); newClassBuilder.make(new TypeResolutionStrategy.Active()).load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION) .getLoaded(); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/WitnessClassFinder.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/WitnessClassFinder.java new file mode 100644 index 0000000000000000000000000000000000000000..8f28b0fa9eea6c761d7ae727aeb908f10e6becfc --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/WitnessClassFinder.java @@ -0,0 +1,42 @@ +package org.skywalking.apm.agent.core.plugin; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import net.bytebuddy.pool.TypePool; + +/** + * The WitnessClassFinder represents a pool of {@link TypePool}s, + * each {@link TypePool} matches a {@link ClassLoader}, + * which helps to find the class define existed or not. + * + * @author wusheng + */ +public enum WitnessClassFinder { + INSTANCE; + + private Map poolMap = new ConcurrentHashMap(); + + /** + * @param witnessClass + * @param classLoader for finding the witnessClass + * @return true, if the given witnessClass exists, through the given classLoader. + */ + public boolean exist(String witnessClass, ClassLoader classLoader) { + ClassLoader mappingKey = classLoader == null ? NullClassLoader.INSTANCE : classLoader; + if (!poolMap.containsKey(witnessClass)) { + synchronized (poolMap) { + if (!poolMap.containsKey(witnessClass)) { + TypePool classTypePool = classLoader == null ? TypePool.Default.ofClassPath() : TypePool.Default.of(classLoader); + poolMap.put(mappingKey, classTypePool); + } + } + } + TypePool typePool = poolMap.get(mappingKey); + TypePool.Resolution witnessClassResolution = typePool.describe(witnessClass); + return witnessClassResolution.isResolved(); + } +} + +final class NullClassLoader extends ClassLoader { + static NullClassLoader INSTANCE = new NullClassLoader(); +} diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefineTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefineTest.java index a35ca44799947722c5140e56591a082339296e15..3a9076ee395849aa7f13cb717dc405e0db091e9b 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefineTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefineTest.java @@ -104,12 +104,12 @@ public class AbstractClassEnhancePluginDefineTest { private DynamicType.Builder transformStaticMethod(DynamicType.Builder newBuilder) { MockPluginStaticMethodInstrumentation staticMethodInstrumentation = new MockPluginStaticMethodInstrumentation(); - return staticMethodInstrumentation.define(WEAVE_CLASS, newBuilder); + return staticMethodInstrumentation.define(WEAVE_CLASS, newBuilder, AbstractClassEnhancePluginDefineTest.class.getClassLoader()); } private DynamicType.Builder transformInstanceMethod(DynamicType.Builder builder) { MockPluginInstanceMethodInstrumentation instrumentation = new MockPluginInstanceMethodInstrumentation(); - return instrumentation.define(WEAVE_CLASS, builder); + return instrumentation.define(WEAVE_CLASS, builder, AbstractClassEnhancePluginDefineTest.class.getClassLoader()); } } diff --git a/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java b/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java index 2fe77d5baa79a8fb6d539157a2a1fde3413ddfbe..3b91cf12c6e904e5e43691f555a5dd44c448f4e8 100644 --- a/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java +++ b/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java @@ -57,7 +57,7 @@ public class SkyWalkingAgent { ClassLoader classLoader) { List pluginDefines = pluginFinder.find(typeDescription.getTypeName()); for (AbstractClassEnhancePluginDefine pluginDefine : pluginDefines) { - DynamicType.Builder newBuilder = pluginDefine.define(typeDescription.getTypeName(), builder); + DynamicType.Builder newBuilder = pluginDefine.define(typeDescription.getTypeName(), builder, classLoader); if (newBuilder != null) { return newBuilder; }