Skip to content

Commit

Permalink
add ClassInjector.getResourceAsStream().
Browse files Browse the repository at this point in the history
  • Loading branch information
jaehong-kim authored and emeroad committed Dec 15, 2016
1 parent 37bab5f commit 0a9c0e4
Show file tree
Hide file tree
Showing 22 changed files with 467 additions and 106 deletions.
Expand Up @@ -20,8 +20,11 @@
import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformCallback;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.InterceptorScope;

import java.io.InputStream;

/**
* @author Woonduk Kang(emeroad)
* @author jaehong.kim
*/
public class GuardInstrumentContext implements InstrumentContext {
private final InstrumentContext instrumentContext;
Expand Down Expand Up @@ -65,6 +68,12 @@ public <T> Class<? extends T> injectClass(ClassLoader targetClassLoader, String
return instrumentContext.injectClass(targetClassLoader, className);
}

@Override
public InputStream getResourceAsStream(ClassLoader targetClassLoader, String className) {
checkOpen();
return instrumentContext.getResourceAsStream(targetClassLoader, className);
}

@Override
public void addClassFileTransformer(ClassLoader classLoader, String targetClassName, TransformCallback transformCallback) {
checkOpen();
Expand Down
Expand Up @@ -20,8 +20,11 @@
import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformCallback;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.InterceptorScope;

import java.io.InputStream;

/**
* @author Woonduk Kang(emeroad)
* @author jaehong.kim
*/
public interface InstrumentContext {

Expand All @@ -35,6 +38,8 @@ public interface InstrumentContext {

<T> Class<? extends T> injectClass(ClassLoader targetClassLoader, String className);

InputStream getResourceAsStream(ClassLoader targetClassLoader, String className);

void addClassFileTransformer(ClassLoader classLoader, String targetClassName, TransformCallback transformCallback);

void addClassFileTransformer(String targetClassName, TransformCallback transformCallback);
Expand Down
Expand Up @@ -62,7 +62,7 @@ public class ASMClass implements InstrumentClass {
private boolean modified = false;

public ASMClass(final InstrumentContext pluginContext, final InterceptorRegistryBinder interceptorRegistryBinder, final ClassLoader classLoader, final ClassNode classNode) {
this(pluginContext, interceptorRegistryBinder, classLoader, new ASMClassNodeAdapter(classLoader, classNode));
this(pluginContext, interceptorRegistryBinder, classLoader, new ASMClassNodeAdapter(pluginContext, classLoader, classNode));
}

public ASMClass(final InstrumentContext pluginContext, final InterceptorRegistryBinder interceptorRegistryBinder, final ClassLoader classLoader, final ASMClassNodeAdapter classNode) {
Expand Down Expand Up @@ -183,7 +183,7 @@ public void weave(final String adviceClassInternalName) throws InstrumentExcepti
throw new NotFoundInstrumentException("advice class internal name must not be null");
}

final ASMClassNodeAdapter adviceClassNode = ASMClassNodeAdapter.get(this.classLoader, JavaAssistUtils.javaNameToJvmName(adviceClassInternalName));
final ASMClassNodeAdapter adviceClassNode = ASMClassNodeAdapter.get(this.pluginContext, this.classLoader, JavaAssistUtils.javaNameToJvmName(adviceClassInternalName));
if (adviceClassNode == null) {
throw new NotFoundInstrumentException(adviceClassInternalName + " not found.");
}
Expand All @@ -200,7 +200,7 @@ public InstrumentMethod addDelegatorMethod(final String methodName, final String
throw new InstrumentException(getName() + " already have method(" + methodName + ").");
}

final ASMClassNodeAdapter superClassNode = ASMClassNodeAdapter.get(this.classLoader, this.classNode.getSuperClassName());
final ASMClassNodeAdapter superClassNode = ASMClassNodeAdapter.get(this.pluginContext, this.classLoader, this.classNode.getSuperClassName());
if (superClassNode == null) {
throw new NotFoundInstrumentException(getName() + " not found super class(" + this.classNode.getSuperClassName() + ")");
}
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package com.navercorp.pinpoint.profiler.instrument;

import com.navercorp.pinpoint.bootstrap.instrument.InstrumentContext;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
Expand All @@ -41,29 +42,18 @@
*/
public class ASMClassNodeAdapter {

public static ASMClassNodeAdapter get(final ClassLoader classLoader, final String className) {
return get(classLoader, className, false);
public static ASMClassNodeAdapter get(final InstrumentContext pluginContext, final ClassLoader classLoader, final String className) {
return get(pluginContext, classLoader, className, false);
}

public static ASMClassNodeAdapter get(final ClassLoader classLoader, final String className, final boolean skipCode) {
if (className == null) {
throw new IllegalArgumentException("class name must not be null.");
}

ClassLoader aClassLoader = classLoader;
if (aClassLoader == null) {
// bootstrap class loader.
aClassLoader = ClassLoader.getSystemClassLoader();
}

if (aClassLoader == null) {
// not initialized system classloader.
return null;
public static ASMClassNodeAdapter get(final InstrumentContext pluginContext, final ClassLoader classLoader, final String className, final boolean skipCode) {
if (pluginContext == null || className == null) {
throw new IllegalArgumentException("plugin context or class name must not be null.");
}

InputStream in = null;
try {
in = aClassLoader.getResourceAsStream(className + ".class");
in = pluginContext.getResourceAsStream(classLoader, className + ".class");
if (in != null) {
final ClassReader classReader = new ClassReader(in);
final ClassNode classNode = new ClassNode();
Expand All @@ -73,7 +63,7 @@ public static ASMClassNodeAdapter get(final ClassLoader classLoader, final Strin
classReader.accept(classNode, 0);
}

return new ASMClassNodeAdapter(classLoader, classNode, skipCode);
return new ASMClassNodeAdapter(pluginContext, classLoader, classNode, skipCode);
}
} catch (IOException ignored) {
// not found class.
Expand All @@ -89,15 +79,17 @@ public static ASMClassNodeAdapter get(final ClassLoader classLoader, final Strin
return null;
}

private final InstrumentContext pluginContext;
private final ClassLoader classLoader;
private final ClassNode classNode;
private final boolean skipCode;

public ASMClassNodeAdapter(final ClassLoader classLoader, final ClassNode classNode) {
this(classLoader, classNode, false);
public ASMClassNodeAdapter(final InstrumentContext pluginContext, final ClassLoader classLoader, final ClassNode classNode) {
this(pluginContext, classLoader, classNode, false);
}

public ASMClassNodeAdapter(final ClassLoader classLoader, final ClassNode classNode, final boolean skipCode) {
public ASMClassNodeAdapter(final InstrumentContext pluginContext, final ClassLoader classLoader, final ClassNode classNode, final boolean skipCode) {
this.pluginContext = pluginContext;
this.classLoader = classLoader;
this.classNode = classNode;
this.skipCode = skipCode;
Expand Down Expand Up @@ -219,7 +211,7 @@ public boolean hasMethod(final String methodName, final String desc) {

if (this.classNode.superName != null) {
// skip code.
final ASMClassNodeAdapter classNode = ASMClassNodeAdapter.get(this.classLoader, this.classNode.superName, true);
final ASMClassNodeAdapter classNode = ASMClassNodeAdapter.get(this.pluginContext, this.classLoader, this.classNode.superName, true);
if (classNode != null) {
return classNode.hasMethod(methodName, desc);
}
Expand Down Expand Up @@ -248,7 +240,7 @@ public ASMFieldNodeAdapter getField(final String fieldName, final String fieldDe
continue;
}

final ASMClassNodeAdapter classNodeAdapter = ASMClassNodeAdapter.get(this.classLoader, interfaceClassName, true);
final ASMClassNodeAdapter classNodeAdapter = ASMClassNodeAdapter.get(this.pluginContext, this.classLoader, interfaceClassName, true);
if (classNodeAdapter != null) {
final ASMFieldNodeAdapter fieldNode = classNodeAdapter.getField(fieldName, fieldDesc);
if (fieldNode != null) {
Expand All @@ -260,7 +252,7 @@ public ASMFieldNodeAdapter getField(final String fieldName, final String fieldDe

// find super class.
if (this.classNode.superName != null) {
final ASMClassNodeAdapter classNodeAdapter = ASMClassNodeAdapter.get(this.classLoader, this.classNode.superName, true);
final ASMClassNodeAdapter classNodeAdapter = ASMClassNodeAdapter.get(this.pluginContext, this.classLoader, this.classNode.superName, true);
if (classNodeAdapter != null) {
final ASMFieldNodeAdapter fieldNode = classNodeAdapter.getField(fieldName, fieldDesc);
if (fieldNode != null) {
Expand Down Expand Up @@ -437,7 +429,7 @@ public boolean subclassOf(final String superInternalName) {
}

// skip code.
classNode = ASMClassNodeAdapter.get(this.classLoader, superClassName, true);
classNode = ASMClassNodeAdapter.get(this.pluginContext, this.classLoader, superClassName, true);
}

return false;
Expand All @@ -455,7 +447,7 @@ public List<ASMClassNodeAdapter> getInnerClasses() {
continue;
}
// skip code.
ASMClassNodeAdapter adapter = get(this.classLoader, node.name, true);
ASMClassNodeAdapter adapter = get(this.pluginContext, this.classLoader, node.name, true);
if (adapter != null) {
innerClasses.add(adapter);
}
Expand All @@ -472,7 +464,7 @@ public byte[] toByteArray() {
flags = ClassWriter.COMPUTE_MAXS;
}

final ClassWriter classWriter = new ASMClassWriter(this.classNode.name, this.classNode.superName, flags, this.classLoader);
final ClassWriter classWriter = new ASMClassWriter(this.pluginContext, this.classNode.name, this.classNode.superName, flags, this.classLoader);
this.classNode.accept(classWriter);
return classWriter.toByteArray();
}
Expand Down
Expand Up @@ -54,7 +54,7 @@ public InstrumentClass getClass(InstrumentContext instrumentContext, ClassLoader

try {
if (classFileBuffer == null) {
ASMClassNodeAdapter classNode = ASMClassNodeAdapter.get(classLoader, JavaAssistUtils.javaNameToJvmName(classInternalName));
ASMClassNodeAdapter classNode = ASMClassNodeAdapter.get(instrumentContext, classLoader, JavaAssistUtils.javaNameToJvmName(classInternalName));
if (classNode == null) {
return null;
}
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package com.navercorp.pinpoint.profiler.instrument;

import com.navercorp.pinpoint.bootstrap.instrument.InstrumentContext;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
Expand All @@ -34,12 +35,14 @@ public final class ASMClassWriter extends ClassWriter {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

private final InstrumentContext pluginContext;
private ClassLoader classLoader;
private String className;
private String superClassName;

public ASMClassWriter(final String className, final String superClassName, final int flags, final ClassLoader classLoader) {
public ASMClassWriter(final InstrumentContext pluginContext, final String className, final String superClassName, final int flags, final ClassLoader classLoader) {
super(flags);
this.pluginContext = pluginContext;
this.className = className;
this.superClassName = superClassName;
this.classLoader = classLoader;
Expand Down Expand Up @@ -197,20 +200,9 @@ private String getSuperClassName(final String className) {
}

private ClassReader getClassReader(final String className) {
ClassLoader aClassLoader = classLoader;
if (aClassLoader == null) {
// bootstrap class loader.
aClassLoader = ClassLoader.getSystemClassLoader();
}

if (aClassLoader == null) {
// not initialized system classloader.
return null;
}

InputStream in = null;
try {
in = aClassLoader.getResourceAsStream(className + ".class");
in = pluginContext.getResourceAsStream(this.classLoader, className + ".class");
if (in != null) {
return new ClassReader(in);
}
Expand Down
Expand Up @@ -20,10 +20,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;

/**
* @author Woonduk Kang(emeroad)
* @author jaehong.kim
*/
public class BootstrapClassLoaderHandler implements ClassInjector {

Expand All @@ -46,7 +48,7 @@ public BootstrapClassLoaderHandler(PluginConfig pluginConfig) {
public <T> Class<? extends T> injectClass(ClassLoader classLoader, String className) {
try {
if (classLoader == null) {
return (Class<T>)injectClass0(className);
return (Class<T>) injectClass0(className);
}
} catch (Exception e) {
logger.warn("Failed to load plugin class {} with classLoader {}", className, classLoader, e);
Expand All @@ -56,15 +58,36 @@ public <T> Class<? extends T> injectClass(ClassLoader classLoader, String classN
}

private Class<?> injectClass0(String className) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
appendToBootstrapClassLoaderSearch();
return Class.forName(className, false, null);
}

private void appendToBootstrapClassLoaderSearch() {
synchronized (lock) {
if (this.injectedToRoot == false) {
this.injectedToRoot = true;
pluginConfig.getInstrumentation().appendToBootstrapClassLoaderSearch(pluginConfig.getPluginJarFile());
pluginConfig.getClassPool().appendToBootstrapClassPath(pluginConfig.getPluginJarFile().getName());
}
}
return Class.forName(className, false, null);
}


}
@Override
public InputStream getResourceAsStream(ClassLoader targetClassLoader, String className) {
try {
if (targetClassLoader == null) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
if (classLoader == null) {
return null;
}
appendToBootstrapClassLoaderSearch();
return classLoader.getResourceAsStream(className);
}
} catch (Exception e) {
logger.warn("Failed to load plugin resource as stream {} with classLoader {}", className, targetClassLoader, e);
return null;
}
logger.warn("Invalid bootstrap class loader. cl={}", targetClassLoader);
return null;
}
}
Expand Up @@ -14,12 +14,16 @@
*/
package com.navercorp.pinpoint.profiler.instrument;

import java.io.InputStream;

/**
* @author Jongho Moon
*
* @author jaehong.kim
*/
public interface ClassInjector {
public interface ClassInjector {

<T> Class<? extends T> injectClass(ClassLoader targetClassLoader, String className);

InputStream getResourceAsStream(ClassLoader targetClassLoader, String className);

}
Expand Up @@ -27,6 +27,7 @@
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

Expand Down Expand Up @@ -183,4 +184,9 @@ private boolean isSkipClass(final String className, final ClassLoadingChecker cl

return false;
}

@Override
public InputStream getResourceAsStream(ClassLoader targetClassLoader, String className) {
return null;
}
}
Expand Up @@ -14,6 +14,7 @@
*/
package com.navercorp.pinpoint.profiler.instrument;

import java.io.InputStream;
import java.net.URLClassLoader;

import com.navercorp.pinpoint.profiler.plugin.PluginConfig;
Expand All @@ -25,7 +26,7 @@

/**
* @author Jongho Moon
*
* @author jaehong.kim
*/
public class JarProfilerPluginClassInjector implements PluginClassInjector {
private final Logger logger = LoggerFactory.getLogger(JarProfilerPluginClassInjector.class);
Expand Down Expand Up @@ -69,4 +70,19 @@ public <T> Class<? extends T> injectClass(ClassLoader classLoader, String classN
}
}

}
public InputStream getResourceAsStream(ClassLoader targetClassLoader, String className) {
try {
if (targetClassLoader == null) {
return bootstrapClassLoaderHandler.getResourceAsStream(null, className);
} else if (targetClassLoader instanceof URLClassLoader) {
final URLClassLoader urlClassLoader = (URLClassLoader) targetClassLoader;
return urlClassLoaderHandler.getResourceAsStream(urlClassLoader, className);
} else {
return plainClassLoaderHandler.getResourceAsStream(targetClassLoader, className);
}
} catch (Throwable e) {
logger.warn("Failed to load plugin resource as stream {} with classLoader {}", className, targetClassLoader, e);
return null;
}
}
}

0 comments on commit 0a9c0e4

Please sign in to comment.