Fix witness class fail, because of different class loaders.
This commit is contained in:
parent
5ff0e98746
commit
d26d925c10
|
|
@ -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 <code>null</code> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<AbstractClassEnhancePluginDefine> loadPlugins() {
|
||||
TypePool classTypePool = TypePool.Default.ofClassPath();
|
||||
|
||||
PluginResourcesResolver resolver = new PluginResourcesResolver();
|
||||
List<URL> 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());
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <code>WitnessClassFinder</code> 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<ClassLoader, TypePool> poolMap = new ConcurrentHashMap<ClassLoader, TypePool>();
|
||||
|
||||
/**
|
||||
* @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();
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public class SkyWalkingAgent {
|
|||
ClassLoader classLoader) {
|
||||
List<AbstractClassEnhancePluginDefine> 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue