Merge branch 'master' of https://github.com/naver/pinpoint into storage-pool

This commit is contained in:
Jaehong Kim
2015-05-22 15:30:22 +09:00
24 changed files with 330 additions and 884 deletions
@@ -1,124 +0,0 @@
/**
* Copyright 2014 NAVER Corp.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.plugin;
import java.lang.reflect.Constructor;
import java.net.URL;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifierHolder;
import com.navercorp.pinpoint.test.plugin.JvmArgument;
import com.navercorp.pinpoint.test.plugin.JvmVersion;
import com.navercorp.pinpoint.test.plugin.OnClassLoader;
import com.navercorp.pinpoint.test.plugin.PinpointPluginTestSuite;
/**
* @author Jongho Moon
*
*/
@RunWith(PinpointPluginTestSuite.class)
@JvmVersion(6)
@OnClassLoader(child=false)
@JvmArgument("-Dcom.navercorp.pinpoint.plugin.classloader=" + Java6PluginClassLoaderIT.JAVA_6_PLUGIN_CLASSLOADER)
public class Java6PluginClassLoaderIT {
public static final String JAVA_6_PLUGIN_CLASSLOADER = "com.navercorp.pinpoint.profiler.plugin.Java6PluginClassLoader";
@Test
public void test() throws Exception {
ClassLoader parent = ClassLoader.getSystemClassLoader();
ClassLoader child = createChildClassLoader(parent);
final int run = 10000;
final int threadNum = 16;
Thread[] thread = new Thread[threadNum];
for (int i = 0; i < threadNum; i++) {
if (i % 2 == 0) {
thread[i] = new Thread(new Parent(parent, child, run));
} else {
thread[i] = new Thread(new Child(child, run));
}
}
for (int i = 0; i < threadNum; i++) {
thread[i].start();
}
System.out.println("Wait workers...");
for (int i = 0; i < threadNum; i++) {
thread[i].join();
}
}
private ClassLoader createChildClassLoader(ClassLoader parent) throws Exception {
Class<? extends ClassLoader> type = PluginTestVerifierHolder.getInstance().getClass().getClassLoader().loadClass(JAVA_6_PLUGIN_CLASSLOADER).asSubclass(ClassLoader.class);
Constructor<? extends ClassLoader> c = type.getConstructor(URL[].class, ClassLoader.class);
return c.newInstance(new URL[0], parent);
}
private static class Parent implements Runnable {
private final ClassLoader parent;
private final ClassLoader child;
private final int count;
public Parent(ClassLoader parent, ClassLoader child, int count) {
this.parent = parent;
this.child = child;
this.count = count;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
System.out.println(this + ": " + i);
synchronized(parent) {
try {
child.loadClass("no.such.Class");
} catch (ClassNotFoundException e) {
// ignore
}
}
}
}
}
private static class Child implements Runnable {
private final ClassLoader child;
private final int count;
public Child(ClassLoader child, int count) {
this.child = child;
this.count = count;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
System.out.println(this + ": " + i);
synchronized(child) {
try {
child.loadClass("no.such.Class");
} catch (ClassNotFoundException e) {
// ignore
}
}
}
}
}
}
@@ -91,8 +91,6 @@ public interface ProfilerPluginContext {
public InterceptorGroup getInterceptorGroup(String name);
public PluginClassLoaderFactory getClassLoaderFactory();
/**
* Add a {@link ApplicationTypeDetector} to Pinpoint agent.
*
@@ -1,103 +0,0 @@
/**
* Copyright 2014 NAVER Corp.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.plugin;
import java.net.URL;
import org.junit.Test;
/**
* @author Jongho Moon
*
*/
public class Java7PluginClassLoaderTest {
@Test
public void test() throws Exception {
ClassLoader parent = ClassLoader.getSystemClassLoader();
ClassLoader child = new Java7PluginClassLoader(new URL[0], parent);
final int run = 10000;
final int threadNum = 16;
Thread[] thread = new Thread[threadNum];
for (int i = 0; i < threadNum; i++) {
if (i % 2 == 0) {
thread[i] = new Thread(new Parent(parent, child, run));
} else {
thread[i] = new Thread(new Child(child, run));
}
}
for (int i = 0; i < threadNum; i++) {
thread[i].start();
}
System.out.println("Wait workers...");
for (int i = 0; i < threadNum; i++) {
thread[i].join();
}
}
private static class Parent implements Runnable {
private final ClassLoader parent;
private final ClassLoader child;
private final int count;
public Parent(ClassLoader parent, ClassLoader child, int count) {
this.parent = parent;
this.child = child;
this.count = count;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
synchronized(parent) {
try {
child.loadClass("no.such.Class");
} catch (ClassNotFoundException e) {
// ignore
}
}
}
}
}
private static class Child implements Runnable {
private final ClassLoader child;
private final int count;
public Child(ClassLoader child, int count) {
this.child = child;
this.count = count;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
synchronized(child) {
try {
child.loadClass("no.such.Class");
} catch (ClassNotFoundException e) {
// ignore
}
}
}
}
}
}
@@ -1,141 +0,0 @@
/**
* Copyright 2014 NAVER Corp.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.security.ProtectionDomain;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.exception.PinpointException;
/**
* @author Jongho Moon
*
*/
public class ClassLoaderResolver {
private final Logger logger = LoggerFactory.getLogger(getClass());
public Class<? extends ClassLoader> resolve(Instrumentation inst) {
String pluginClassLoaderName = null;
String specified = System.getProperty("com.navercorp.pinpoint.plugin.classloader");
if (specified == null) {
pluginClassLoaderName = resolveClassLoaderType();
} else {
pluginClassLoaderName = specified;
}
logger.info("Use plugin class loader: " + pluginClassLoaderName);
boolean redefineClassLoader = "com.navercorp.pinpoint.profiler.plugin.Java6PluginClassLoader".equals(pluginClassLoaderName);
try {
if (redefineClassLoader) {
retransformClassLoader(inst);
}
return Class.forName(pluginClassLoaderName).asSubclass(ClassLoader.class);
} catch (ClassNotFoundException e) {
throw new NoClassDefFoundError("Cannot find plugin class loader: " + pluginClassLoaderName);
} catch (Exception e) {
throw new PinpointException("Failed to prepare " + pluginClassLoaderName, e);
}
}
private String resolveClassLoaderType() {
String pluginClassLoaderName;
boolean java6 = isJava6();
boolean unsafe = hasUnsafe();
if (java6) {
if (unsafe) {
pluginClassLoaderName = "com.navercorp.pinpoint.profiler.plugin.Java6UnsafePluginClassLoader";
} else {
pluginClassLoaderName = "com.navercorp.pinpoint.profiler.plugin.Java6PluginClassLoader";
}
} else {
pluginClassLoaderName = "com.navercorp.pinpoint.profiler.plugin.Java7PluginClassLoader";
}
return pluginClassLoaderName;
}
private void retransformClassLoader(Instrumentation inst) throws UnmodifiableClassException {
ClassLoaderTransformer transformer = new ClassLoaderTransformer();
inst.addTransformer(transformer, true);
inst.retransformClasses(ClassLoader.class);
inst.removeTransformer(transformer);
}
private boolean hasUnsafe() {
try {
Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe").setAccessible(true);
} catch (Exception e) {
return false;
}
return true;
}
private boolean isJava6() {
try {
ClassLoader.class.getDeclaredMethod("registerAsParallelCapable");
} catch (Exception e) {
return true;
}
return false;
}
private static class ClassLoaderTransformer implements ClassFileTransformer {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
logger.info("in transform: " + className);
if (className.equals("java/lang/ClassLoader")) {
logger.info("Transform ClassLoader");
try {
ClassPool classPool = new ClassPool(true);
CtClass c = classPool.get("java.lang.ClassLoader");
CtMethod m = c.getMethod("loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;");
m.insertBefore("com.navercorp.pinpoint.bootstrap.ClassLoaderLock.lock(this);");
m.insertAfter("com.navercorp.pinpoint.bootstrap.ClassLoaderLock.unlock(this);", true);
logger.info("Transform ClassLoader Finished");
return c.toBytecode();
} catch (Exception e) {
return null;
}
}
return null;
}
}
}
@@ -18,8 +18,6 @@ package com.navercorp.pinpoint.profiler;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -38,9 +36,7 @@ import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerBinder;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin;
import com.navercorp.pinpoint.bootstrap.sampler.Sampler;
import com.navercorp.pinpoint.common.plugin.PluginLoader;
import com.navercorp.pinpoint.common.service.ServiceTypeRegistryService;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.context.DefaultServerMetaDataHolder;
@@ -53,8 +49,8 @@ import com.navercorp.pinpoint.profiler.interceptor.InterceptorRegistryBinder;
import com.navercorp.pinpoint.profiler.interceptor.bci.JavaAssistByteCodeInstrumentor;
import com.navercorp.pinpoint.profiler.logging.Slf4jLoggerBinder;
import com.navercorp.pinpoint.profiler.monitor.AgentStatMonitor;
import com.navercorp.pinpoint.profiler.plugin.DefaultPluginClassLoaderFactory;
import com.navercorp.pinpoint.profiler.plugin.DefaultProfilerPluginContext;
import com.navercorp.pinpoint.profiler.plugin.ProfilerPluginLoader;
import com.navercorp.pinpoint.profiler.receiver.CommandDispatcher;
import com.navercorp.pinpoint.profiler.receiver.service.EchoService;
import com.navercorp.pinpoint.profiler.receiver.service.ThreadDumpService;
@@ -106,7 +102,6 @@ public class DefaultAgent implements Agent {
private final InterceptorRegistryBinder interceptorRegistryBinder;
private final ServiceTypeRegistryService serviceTypeRegistryService;
private final DefaultPluginClassLoaderFactory pluginClassLoaderFactory;
private final List<DefaultProfilerPluginContext> pluginContexts;
@@ -160,9 +155,7 @@ public class DefaultAgent implements Agent {
logger.info("DefaultAgent classLoader:{}", this.getClass().getClassLoader());
}
Class<? extends ClassLoader> classLoaderType = new ClassLoaderResolver().resolve(instrumentation);
pluginClassLoaderFactory = new DefaultPluginClassLoaderFactory(classLoaderType, agentOption.getPluginJars());
pluginContexts = loadProfilerPlugins(agentOption.getPluginJars());
pluginContexts = loadPlugins(agentOption);
this.classFileTransformer = new ClassFileTransformerDispatcher(this, byteCodeInstrumentor, pluginContexts);
retransformService.setRetransformEventListener(classFileTransformer);
@@ -199,6 +192,10 @@ public class DefaultAgent implements Agent {
this.agentStatMonitor = new AgentStatMonitor(this.statDataSender, this.agentInformation.getAgentId(), this.agentInformation.getStartTime());
}
protected List<DefaultProfilerPluginContext> loadPlugins(AgentOption agentOption) {
return new ProfilerPluginLoader(this).load(agentOption.getPluginJars());
}
private CommandDispatcher createCommandDispatcher() {
CommandDispatcher commandDispatcher = new CommandDispatcher();
@@ -207,22 +204,6 @@ public class DefaultAgent implements Agent {
return commandDispatcher;
}
private List<DefaultProfilerPluginContext> loadProfilerPlugins(URL[] pluginJars) {
List<ProfilerPlugin> plugins = PluginLoader.load(ProfilerPlugin.class, pluginJars);
List<DefaultProfilerPluginContext> pluginContexts = new ArrayList<DefaultProfilerPluginContext>(plugins.size());
for (ProfilerPlugin plugin : plugins) {
logger.info("Loading plugin: {}", plugin.getClass().getName());
DefaultProfilerPluginContext context = new DefaultProfilerPluginContext(this);
plugin.setup(context);
context.markInitialized();
pluginContexts.add(context);
}
return pluginContexts;
}
public ByteCodeInstrumentor getByteCodeInstrumentor() {
return byteCodeInstrumentor;
}
@@ -383,10 +364,6 @@ public class DefaultAgent implements Agent {
return serviceTypeRegistryService;
}
public DefaultPluginClassLoaderFactory getPluginClassLoaderFactory() {
return pluginClassLoaderFactory;
}
@Override
public void start() {
synchronized (this) {
@@ -1,136 +0,0 @@
/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.plugin;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.PluginClassLoaderFactory;
import com.navercorp.pinpoint.exception.PinpointException;
public class DefaultPluginClassLoaderFactory implements PluginClassLoaderFactory {
private static final Logger logger = LoggerFactory.getLogger(DefaultPluginClassLoaderFactory.class);
private static final SecurityManager SECURITY_MANAGER = System.getSecurityManager();
private final Constructor<? extends ClassLoader> classLoaderConstructor;
private final URL[] pluginJars;
private final ConcurrentHashMap<ClassLoader, ClassLoader> cache = new ConcurrentHashMap<ClassLoader, ClassLoader>();
private final AtomicReference<ClassLoader> forBootstrapClassLoader = new AtomicReference<ClassLoader>();
public DefaultPluginClassLoaderFactory(Class<? extends ClassLoader> classLoaderType, URL[] pluginJars) {
try {
this.classLoaderConstructor = classLoaderType.getDeclaredConstructor(URL[].class, ClassLoader.class);
} catch (Exception e) {
throw new PinpointException("Cannot find constructor with parameter (URL[], ClassLoader): " + classLoaderType);
}
this.pluginJars = pluginJars;
}
@Override
public ClassLoader get(ClassLoader loader) {
if (loader == null) {
// boot class loader
return getForBootstrap();
} else {
return getForPlain(loader);
}
}
private ClassLoader getForPlain(ClassLoader loader) {
final ClassLoader forPlugin = cache.get(loader);
if (forPlugin != null) {
return forPlugin;
}
final ClassLoader newInstance = createPluginClassLoader(pluginJars, loader);
final ClassLoader before = cache.putIfAbsent(loader, newInstance);
if (before == null) {
return newInstance;
} else {
close (newInstance);
return before;
}
}
private ClassLoader getForBootstrap() {
final ClassLoader forPlugin = forBootstrapClassLoader.get();
if (forPlugin != null) {
return forPlugin;
}
// Strictly, should pass null as parent class loader.
// But if so, All the types used by interceptors have to be loaded by bootstrap class loader.
// So we use system class loader as parent.
final ClassLoader newInstance = createPluginClassLoader(pluginJars, ClassLoader.getSystemClassLoader());
boolean success = forBootstrapClassLoader.compareAndSet(null, newInstance);
if (success) {
return newInstance;
} else {
close (newInstance);
return forBootstrapClassLoader.get();
}
}
private ClassLoader createPluginClassLoader(final URL[] urls, final ClassLoader parent) {
if (SECURITY_MANAGER != null) {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return createPluginClassLoader0(urls, parent);
}
});
} else {
return createPluginClassLoader0(urls, parent);
}
}
private ClassLoader createPluginClassLoader0(URL[] urls, ClassLoader parent) {
try {
return (ClassLoader)classLoaderConstructor.newInstance(urls, parent);
} catch (Exception e) {
throw new PinpointException("Failed to create plugin classloader instance", e);
}
}
private void close(ClassLoader classLoader) {
if (classLoader == null) {
return;
}
// after jdk 1.7
if (classLoader instanceof Closeable) {
try {
((Closeable)classLoader).close();
} catch (IOException e) {
logger.warn("ClassLoader.close() fail. Cause: " + e.getMessage(), e);
}
}
}
}
@@ -29,7 +29,6 @@ import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroup;
import com.navercorp.pinpoint.bootstrap.plugin.ApplicationTypeDetector;
import com.navercorp.pinpoint.bootstrap.plugin.PluginClassLoaderFactory;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassFileTransformerBuilder;
import com.navercorp.pinpoint.profiler.DefaultAgent;
@@ -38,6 +37,7 @@ import com.navercorp.pinpoint.profiler.util.NameValueList;
public class DefaultProfilerPluginContext implements ProfilerPluginContext {
private final DefaultAgent agent;
private final ProfilerPluginClassLoader classInjector;
private final List<ApplicationTypeDetector> serverTypeDetectors = new ArrayList<ApplicationTypeDetector>();
private final List<ClassFileTransformer> classTransformers = new ArrayList<ClassFileTransformer>();
@@ -53,8 +53,9 @@ public class DefaultProfilerPluginContext implements ProfilerPluginContext {
private boolean initialized = false;
public DefaultProfilerPluginContext(DefaultAgent agent) {
public DefaultProfilerPluginContext(DefaultAgent agent, ProfilerPluginClassLoader classInjector) {
this.agent = agent;
this.classInjector = classInjector;
}
@Override
@@ -152,10 +153,9 @@ public class DefaultProfilerPluginContext implements ProfilerPluginContext {
serverTypeDetectors.add(detector);
}
}
@Override
public PluginClassLoaderFactory getClassLoaderFactory() {
return agent.getPluginClassLoaderFactory();
public ProfilerPluginClassLoader getClassInjector() {
return classInjector;
}
public List<ClassFileTransformer> getClassEditors() {
@@ -0,0 +1,171 @@
/**
* Copyright 2014 NAVER Corp.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.plugin;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.jar.JarFile;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.exception.PinpointException;
/**
* @author Jongho Moon
*
*/
public class JarProfilerPluginClassLoader implements ProfilerPluginClassLoader {
private static final Logger logger = LoggerFactory.getLogger(JarProfilerPluginClassLoader.class);
private static final Method ADD_URL;
private static final Method DEFINE_CLASS;
static {
try {
ADD_URL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
ADD_URL.setAccessible(true);
} catch (Exception e) {
throw new PinpointException("Cannot access URLClassLoader.addURL(URL)", e);
}
try {
DEFINE_CLASS = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
DEFINE_CLASS.setAccessible(true);
} catch (Exception e) {
throw new PinpointException("Cannot access ClassLoader.defineClass(String, byte[], int, int)", e);
}
}
public static JarProfilerPluginClassLoader of(URL pluginJar) {
try {
JarFile jarFile = new JarFile(new File(pluginJar.toURI()));
return new JarProfilerPluginClassLoader(pluginJar, jarFile);
} catch (Exception e) {
logger.warn("Failed to get JarFile {}", pluginJar, e);
return null;
}
}
private final URL pluginJarURL;
private final JarFile pluginJar;
private JarProfilerPluginClassLoader(URL pluginJarURL, JarFile pluginJar) {
this.pluginJarURL = pluginJarURL;
this.pluginJar = pluginJar;
}
@Override
@SuppressWarnings("unchecked")
public <T> Class<? extends T> loadClass(ClassLoader classLoader, String className) {
ClassLoader targetClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
try {
if (targetClassLoader instanceof URLClassLoader) {
return (Class<T>)loadFromURLClassLoader((URLClassLoader)targetClassLoader, className);
} else {
return (Class<T>)loadFromOtherClassLoader(targetClassLoader, className);
}
} catch (Exception e) {
logger.warn("Failed to load plugin class {} with classLoader {}", className, targetClassLoader, e);
throw new PinpointException("Failed to load plugin class " + className + " with classLoader " + targetClassLoader, e);
}
}
private Class<?> loadFromURLClassLoader(URLClassLoader classLoader, String className) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
URL[] urls = classLoader.getURLs();
boolean hasPluginJar = false;
for (URL url : urls) {
if (url.equals(pluginJarURL)) {
hasPluginJar = true;
break;
}
}
if (!hasPluginJar) {
ADD_URL.invoke(classLoader, pluginJarURL);
}
return classLoader.loadClass(className);
}
private Class<?> loadFromOtherClassLoader(ClassLoader classLoader, String className) throws NotFoundException, IllegalArgumentException, IOException, CannotCompileException, IllegalAccessException, InvocationTargetException {
ClassPool pool = new ClassPool();
pool.appendClassPath(new LoaderClassPath(classLoader));
pool.appendClassPath(pluginJar.getName());
return loadFromOtherClassLoader(pool, classLoader, className);
}
private Class<?> loadFromOtherClassLoader(ClassPool pool, ClassLoader classLoader, String className) throws NotFoundException, IOException, CannotCompileException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Class<?> c = null;
try {
c = classLoader.loadClass(className);
} catch (ClassNotFoundException e) {
}
if (c != null) {
return c;
}
CtClass ct = pool.get(className);
if (ct == null) {
throw new NotFoundException(className);
}
CtClass superClass = ct.getSuperclass();
if (superClass != null) {
loadFromOtherClassLoader(pool, classLoader, superClass.getName());
}
CtClass[] interfaces = ct.getInterfaces();
for (CtClass i : interfaces) {
loadFromOtherClassLoader(pool, classLoader, i.getName());
}
Collection<String> refs = ct.getRefClasses();
for (String ref : refs) {
try {
loadFromOtherClassLoader(pool, classLoader, ref);
} catch (NotFoundException e) {
logger.warn("Skip a referenced class because of NotFoundException : ", e);
}
}
byte[] bytes = ct.toBytecode();
return (Class<?>)DEFINE_CLASS.invoke(classLoader, ct.getName(), bytes, 0, bytes.length);
}
}
@@ -1,59 +0,0 @@
/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.plugin;
import java.net.URL;
import java.net.URLClassLoader;
import com.navercorp.pinpoint.bootstrap.ClassLoaderLock;
/**
* @author Jongho Moon
* @author emeroad
*/
public class Java6PluginClassLoader extends URLClassLoader {
public Java6PluginClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
ClassLoaderLock.register(parent, this);
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
ClassLoaderLock.lock(this);
try {
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
c = getParent().loadClass(name);
} catch (ClassNotFoundException e) {
}
if (c == null) {
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
} finally {
ClassLoaderLock.unlock(this);
}
}
}
@@ -1,97 +0,0 @@
/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.plugin;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import sun.misc.Unsafe;
/**
* @author Jongho Moon
* @author emeroad
*/
@SuppressWarnings("restriction")
public class Java6UnsafePluginClassLoader extends URLClassLoader {
private static final Unsafe unsafe;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe)f.get(null);
// Ensure required classes are loaded
while (!unsafe.tryMonitorEnter(Java6UnsafePluginClassLoader.class)) { }
Java6UnsafePluginClassLoader.class.wait(0, 1);
unsafe.monitorExit(Java6UnsafePluginClassLoader.class);
} catch (Exception e) {
throw new RuntimeException("Failed to get unsafe", e);
}
}
private final ClassLoader parent;
public Java6UnsafePluginClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
this.parent = parent;
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> c = null;
synchronized (this) {
c = findLoadedClass(name);
if (c == null) {
try {
while (!unsafe.tryMonitorEnter(parent)) {
try {
this.wait(0, 1);
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted", e);
}
}
try {
c = parent.loadClass(name);
} finally {
unsafe.monitorExit(parent);
}
} catch (ClassNotFoundException e) {
}
if (c == null) {
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
this.notify();
}
return c;
}
}
@@ -12,14 +12,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.bootstrap.plugin;
package com.navercorp.pinpoint.profiler.plugin;
/**
* @author Jongho Moon
*
*/
public interface PluginClassLoaderFactory {
public interface ProfilerPluginClassLoader {
public ClassLoader get(ClassLoader loader);
public <T> Class<? extends T> loadClass(ClassLoader targetClassLoader, String className);
}
@@ -0,0 +1,61 @@
/**
* Copyright 2014 NAVER Corp.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.plugin;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin;
import com.navercorp.pinpoint.common.plugin.PluginLoader;
import com.navercorp.pinpoint.profiler.DefaultAgent;
/**
* @author Jongho Moon
*
*/
public class ProfilerPluginLoader {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final DefaultAgent agent;
public ProfilerPluginLoader(DefaultAgent agent) {
this.agent = agent;
}
public List<DefaultProfilerPluginContext> load(URL[] pluginJars) {
List<DefaultProfilerPluginContext> pluginContexts = new ArrayList<DefaultProfilerPluginContext>(pluginJars.length);
for (URL jar : pluginJars) {
List<ProfilerPlugin> plugins = PluginLoader.load(ProfilerPlugin.class, new URL[] { jar });
for (ProfilerPlugin plugin : plugins) {
logger.info("Loading plugin: {}", plugin.getClass().getName());
ProfilerPluginClassLoader classInjector = JarProfilerPluginClassLoader.of(jar);
DefaultProfilerPluginContext context = new DefaultProfilerPluginContext(agent, classInjector);
plugin.setup(context);
context.markInitialized();
pluginContexts.add(context);
}
}
return pluginContexts;
}
}
@@ -60,23 +60,7 @@ public final class TypeUtils {
return result;
}
@SuppressWarnings("unchecked")
public static <T> Class<T> loadClass(ClassLoader loader, String className) {
Thread currentThread = Thread.currentThread();
ClassLoader backup = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(loader);
try {
return (Class<T>)loader.loadClass(className);
} catch (ClassNotFoundException e) {
throw new PinpointException("Cannot load class: " + className, e);
} finally {
currentThread.setContextClassLoader(backup);
}
}
public static <T extends Annotation> T findAnnotation(Annotation[] annotations, Class<T> type) {
for (Annotation a : annotations) {
if (a.annotationType() == type) {
@@ -54,7 +54,7 @@ public class AnnotatedInterceptorInjector implements MethodRecipe {
}
int inject(ClassLoader targetClassLoader, InstrumentClass targetClass, MethodInfo targetMethod) throws Exception {
Class<? extends Interceptor> interceptorType = TypeUtils.loadClass(targetClassLoader, interceptorClassName);
Class<? extends Interceptor> interceptorType = pluginContext.getClassInjector().loadClass(targetClassLoader, interceptorClassName);
InterceptorFactory factory = createInterceptorFactory(interceptorType);
Interceptor interceptor = factory.getInterceptor(targetClassLoader, targetClass, targetMethod);
@@ -29,7 +29,6 @@ import com.navercorp.pinpoint.bootstrap.plugin.annotation.TargetMethod;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Targets;
import com.navercorp.pinpoint.exception.PinpointException;
import com.navercorp.pinpoint.profiler.plugin.DefaultProfilerPluginContext;
import com.navercorp.pinpoint.profiler.plugin.TypeUtils;
import com.navercorp.pinpoint.profiler.plugin.objectfactory.AutoBindingObjectFactory;
import com.navercorp.pinpoint.profiler.plugin.transformer.ClassCookBook;
import com.navercorp.pinpoint.profiler.plugin.transformer.ClassRecipe;
@@ -46,16 +45,16 @@ import com.navercorp.pinpoint.profiler.plugin.transformer.MethodTransformer;
public class TargetAnnotatedInterceptorInjector implements ClassRecipe {
private final DefaultProfilerPluginContext pluginContext;
private final String interceptorName;
private final String interceptorClassName;
private final Object[] providedArguments;
private final String groupName;
private final ExecutionPolicy executionPoint;
public TargetAnnotatedInterceptorInjector(DefaultProfilerPluginContext pluginContext, String interceptorName, Object[] providedArguments, String groupName, ExecutionPolicy executionPoint) {
public TargetAnnotatedInterceptorInjector(DefaultProfilerPluginContext pluginContext, String interceptorClassName, Object[] providedArguments, String groupName, ExecutionPolicy executionPoint) {
this.pluginContext = pluginContext;
this.interceptorName = interceptorName;
this.interceptorClassName = interceptorClassName;
this.providedArguments = providedArguments;
this.groupName = groupName;
this.executionPoint = executionPoint;
@@ -63,9 +62,9 @@ public class TargetAnnotatedInterceptorInjector implements ClassRecipe {
@Override
public void edit(ClassLoader classLoader, InstrumentClass target) throws Throwable {
Class<? extends Interceptor> interceptorType = TypeUtils.loadClass(classLoader, interceptorName);
Class<? extends Interceptor> interceptorType = pluginContext.getClassInjector().loadClass(classLoader, interceptorClassName);
AnnotatedInterceptorInjector injector = new AnnotatedInterceptorInjector(pluginContext, interceptorName, providedArguments, groupName, executionPoint);
AnnotatedInterceptorInjector injector = new AnnotatedInterceptorInjector(pluginContext, interceptorClassName, providedArguments, groupName, executionPoint);
ClassRecipe recipe = createMethodEditor(classLoader, interceptorType, target, injector);
recipe.edit(classLoader, target);
@@ -106,7 +105,7 @@ public class TargetAnnotatedInterceptorInjector implements ClassRecipe {
}
if (editors.isEmpty()) {
throw new PinpointException("No target is specified. At least one of @Targets, @TargetMethod, @TargetConstructor, @TargetFilter must present. interceptor: " + interceptorName);
throw new PinpointException("No target is specified. At least one of @Targets, @TargetMethod, @TargetConstructor, @TargetFilter must present. interceptor: " + interceptorClassName);
}
return editors.size() == 1 ? editors.get(0) : new ClassCookBook(editors);
@@ -116,7 +115,7 @@ public class TargetAnnotatedInterceptorInjector implements ClassRecipe {
String methodName = annotation.name();
if (methodName == null) {
throw new PinpointException("name() of @TargetMethod cannot be null: " + interceptorName);
throw new PinpointException("name() of @TargetMethod cannot be null: " + interceptorClassName);
}
String[] parameterTypeNames = annotation.paramTypes();
@@ -133,7 +132,7 @@ public class TargetAnnotatedInterceptorInjector implements ClassRecipe {
String type = annotation.type();
if (type == null) {
throw new PinpointException("type of @TargetFilter is null: " + interceptorName);
throw new PinpointException("type of @TargetFilter is null: " + interceptorClassName);
}
AutoBindingObjectFactory filterFactory = new AutoBindingObjectFactory(pluginContext, targetClass, classLoader);
@@ -147,7 +146,7 @@ public class TargetAnnotatedInterceptorInjector implements ClassRecipe {
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("TargetAnnotatedInterceptorInjector [interceptorClass=");
builder.append(interceptorName);
builder.append(interceptorClassName);
if (providedArguments != null) {
builder.append(", constructorArguments=");
@@ -26,29 +26,30 @@ import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroup;
import com.navercorp.pinpoint.bootstrap.plugin.ObjectRecipe;
import com.navercorp.pinpoint.bootstrap.plugin.ObjectRecipe.ByConstructor;
import com.navercorp.pinpoint.bootstrap.plugin.ObjectRecipe.ByStaticFactoryMethod;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext;
import com.navercorp.pinpoint.exception.PinpointException;
import com.navercorp.pinpoint.profiler.plugin.TypeUtils;
import com.navercorp.pinpoint.profiler.plugin.DefaultProfilerPluginContext;
/**
* @author Jongho Moon
*
*/
public class AutoBindingObjectFactory {
private final DefaultProfilerPluginContext pluginContext;
private final ClassLoader classLoader;
private final PinpointTypeArgumentProvider pinpointResolver;
public AutoBindingObjectFactory(ProfilerPluginContext pluginContext, InstrumentClass targetClass, ClassLoader classLoader) {
public AutoBindingObjectFactory(DefaultProfilerPluginContext pluginContext, InstrumentClass targetClass, ClassLoader classLoader) {
this(pluginContext, null, targetClass, null, classLoader);
}
public AutoBindingObjectFactory(ProfilerPluginContext pluginContext, InterceptorGroup interceptorGroup, InstrumentClass targetClass, MethodInfo targetMethod, ClassLoader classLoader) {
public AutoBindingObjectFactory(DefaultProfilerPluginContext pluginContext, InterceptorGroup interceptorGroup, InstrumentClass targetClass, MethodInfo targetMethod, ClassLoader classLoader) {
this.pluginContext = pluginContext;
this.classLoader = classLoader;
this.pinpointResolver = new PinpointTypeArgumentProvider(pluginContext, interceptorGroup, targetClass, targetMethod);
}
public Object createInstance(ObjectRecipe recipe) {
Class<?> type = TypeUtils.loadClass(classLoader, recipe.getClassName());
Class<?> type = pluginContext.getClassInjector().loadClass(classLoader, recipe.getClassName());
ArgumentsResolver argumentsResolver = getParameterResolvers(classLoader, recipe.getArguments());
if (recipe instanceof ByConstructor) {
@@ -23,45 +23,34 @@ import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.plugin.PluginClassLoaderFactory;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.PinpointClassFileTransformer;
import com.navercorp.pinpoint.exception.PinpointException;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
public class DedicatedClassFileTransformer implements PinpointClassFileTransformer {
private final ByteCodeInstrumentor instrumentor;
private final PluginClassLoaderFactory classLoaderFactory;
private final String targetClassName;
private final ClassRecipe recipe;
public DedicatedClassFileTransformer(ByteCodeInstrumentor instrumentor, PluginClassLoaderFactory classLoaderFactory, String targetClassName, ClassRecipe recipe) {
public DedicatedClassFileTransformer(ByteCodeInstrumentor instrumentor, String targetClassName, ClassRecipe recipe) {
this.instrumentor = instrumentor;
this.classLoaderFactory = classLoaderFactory;
this.targetClassName = targetClassName;
this.recipe = recipe;
}
@Override
public byte[] transform(ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
ClassLoader forPlugin = classLoaderFactory.get(classLoader);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(forPlugin);
try {
InstrumentClass target = instrumentor.getClass(classLoader, className, classfileBuffer);
recipe.edit(forPlugin, target);
recipe.edit(classLoader, target);
return target.toBytecode();
} catch (PinpointException e) {
throw e;
} catch (Throwable e) {
String msg = "Fail to invoke plugin class recipe: " + toString();
throw new PinpointException(msg, e);
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
@@ -123,7 +123,7 @@ public class DefaultClassFileTransformerBuilder implements ClassFileTransformerB
@Override
public PinpointClassFileTransformer build() {
ClassRecipe recipe = buildClassRecipe();
return new DedicatedClassFileTransformer(pluginContext.getByteCodeInstrumentor(), pluginContext.getClassLoaderFactory(), targetClassName, recipe);
return new DedicatedClassFileTransformer(pluginContext.getByteCodeInstrumentor(), targetClassName, recipe);
}
private ClassRecipe buildClassRecipe() {
@@ -19,25 +19,30 @@ package com.navercorp.pinpoint.test;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.thrift.TBase;
import com.navercorp.pinpoint.bootstrap.AgentOption;
import com.navercorp.pinpoint.bootstrap.DefaultAgentOption;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.context.ServerMetaDataHolder;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin;
import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier.ExpectedAnnotation;
import com.navercorp.pinpoint.common.plugin.PluginLoader;
import com.navercorp.pinpoint.common.service.DefaultAnnotationKeyRegistryService;
import com.navercorp.pinpoint.common.service.DefaultServiceTypeRegistryService;
import com.navercorp.pinpoint.common.trace.ServiceType;
import org.apache.thrift.TBase;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.context.ServerMetaDataHolder;
import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier.ExpectedAnnotation;
import com.navercorp.pinpoint.exception.PinpointException;
import com.navercorp.pinpoint.profiler.DefaultAgent;
import com.navercorp.pinpoint.profiler.context.Span;
import com.navercorp.pinpoint.profiler.context.SpanEvent;
import com.navercorp.pinpoint.profiler.context.storage.StorageFactory;
import com.navercorp.pinpoint.profiler.interceptor.GlobalInterceptorRegistryBinder;
import com.navercorp.pinpoint.profiler.plugin.DefaultProfilerPluginContext;
import com.navercorp.pinpoint.profiler.plugin.ProfilerPluginClassLoader;
import com.navercorp.pinpoint.profiler.receiver.CommandDispatcher;
import com.navercorp.pinpoint.profiler.sender.DataSender;
import com.navercorp.pinpoint.profiler.sender.EnhancedDataSender;
@@ -108,6 +113,25 @@ public class MockAgent extends DefaultAgent {
return new ResettableServerMetaDataHolder(vmArgs);
}
@Override
protected List<DefaultProfilerPluginContext> loadPlugins(AgentOption agentOption) {
List<DefaultProfilerPluginContext> pluginContexts = new ArrayList<DefaultProfilerPluginContext>();
ProfilerPluginClassLoader classInjector = new TestProfilerPluginClassLoader();
List<ProfilerPlugin> plugins = PluginLoader.load(ProfilerPlugin.class, ClassLoader.getSystemClassLoader());
for (ProfilerPlugin plugin : plugins) {
DefaultProfilerPluginContext context = new DefaultProfilerPluginContext(this, classInjector);
plugin.setup(context);
context.markInitialized();
pluginContexts.add(context);
}
return pluginContexts;
}
public static String toString(Span span) {
StringBuilder builder = new StringBuilder();
builder.append('(');
@@ -1,40 +1,35 @@
/*
/**
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.test;
package com.navercorp.pinpoint.profiler.plugin;
import java.net.URL;
import java.net.URLClassLoader;
import com.navercorp.pinpoint.exception.PinpointException;
import com.navercorp.pinpoint.profiler.plugin.ProfilerPluginClassLoader;
/**
* @author Jongho Moon
* @author emeroad
*
*/
public class Java7PluginClassLoader extends URLClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
public Java7PluginClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public class TestProfilerPluginClassLoader implements ProfilerPluginClassLoader {
@SuppressWarnings("unchecked")
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// for debugging
return super.loadClass(name, resolve);
public <T> Class<? extends T> loadClass(ClassLoader targetClassLoader, String className) {
try {
return (Class<? extends T>) targetClassLoader.loadClass(className);
} catch (ClassNotFoundException e) {
throw new PinpointException("Cannot find class: " + className, e);
}
}
}
@@ -20,8 +20,6 @@ import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import java.lang.instrument.ClassFileTransformer;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.Test;
@@ -36,6 +34,7 @@ import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerBuilder;
import com.navercorp.pinpoint.profiler.DefaultAgent;
import com.navercorp.pinpoint.profiler.plugin.transformer.DefaultClassFileTransformerBuilder;
import com.navercorp.pinpoint.test.TestProfilerPluginClassLoader;
public class DefaultClassEditorBuilderTest {
public static final String SCOPE_NAME = "test";
@@ -47,11 +46,9 @@ public class DefaultClassEditorBuilderTest {
InstrumentClass aClass = mock(InstrumentClass.class);
MethodInfo aMethod = mock(MethodInfo.class);
MethodDescriptor aDescriptor = mock(MethodDescriptor.class);
DefaultPluginClassLoaderFactory classLoaderFactory = mock(DefaultPluginClassLoaderFactory.class);
DefaultAgent agent = mock(DefaultAgent.class);
ClassLoader classLoader = getClass().getClassLoader();
ClassLoader childClassLoader = new URLClassLoader(new URL[0], classLoader);
String className = "someClass";
String methodName = "someMethod";
byte[] classFileBuffer = new byte[0];
@@ -60,8 +57,6 @@ public class DefaultClassEditorBuilderTest {
when(agent.getByteCodeInstrumentor()).thenReturn(instrumentor);
when(agent.getTraceContext()).thenReturn(traceContext);
when(agent.getPluginClassLoaderFactory()).thenReturn(classLoaderFactory);
when(classLoaderFactory.get(classLoader)).thenReturn(childClassLoader);
when(instrumentor.getClass(classLoader, className, classFileBuffer)).thenReturn(aClass);
when(aClass.getDeclaredMethod(methodName, parameterTypeNames)).thenReturn(aMethod);
when(aMethod.getName()).thenReturn(methodName);
@@ -69,7 +64,8 @@ public class DefaultClassEditorBuilderTest {
when(aMethod.getDescriptor()).thenReturn(aDescriptor);
when(aClass.addInterceptor(eq(methodName), eq(parameterTypeNames), isA(Interceptor.class))).thenReturn(0);
DefaultProfilerPluginContext context = new DefaultProfilerPluginContext(agent);
DefaultProfilerPluginContext context = new DefaultProfilerPluginContext(agent, new TestProfilerPluginClassLoader());
DefaultClassFileTransformerBuilder builder = new DefaultClassFileTransformerBuilder(context, "TargetClass");
builder.injectMetadata("a", "java.util.HashMap");
builder.injectFieldAccessor("someField");
@@ -37,6 +37,7 @@ import com.navercorp.pinpoint.profiler.plugin.TestInterceptors.TestInterceptor0;
import com.navercorp.pinpoint.profiler.plugin.TestInterceptors.TestInterceptor1;
import com.navercorp.pinpoint.profiler.plugin.TestInterceptors.TestInterceptor2;
import com.navercorp.pinpoint.profiler.plugin.interceptor.AnnotatedInterceptorFactory;
import com.navercorp.pinpoint.test.TestProfilerPluginClassLoader;
public class DefaultInterceptorFactoryTest {
private final DefaultProfilerPluginContext pluginContext = mock(DefaultProfilerPluginContext.class);
@@ -50,6 +51,7 @@ public class DefaultInterceptorFactoryTest {
public void setUp() {
reset(instrumentor, traceContext, aClass, aMethod);
when(pluginContext.getTraceContext()).thenReturn(traceContext);
when(pluginContext.getClassInjector()).thenReturn(new TestProfilerPluginClassLoader());
when(aMethod.getDescriptor()).thenReturn(descriptor);
}
@@ -1,103 +0,0 @@
/**
* Copyright 2014 NAVER Corp.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.plugin;
import java.net.URL;
import org.junit.Test;
/**
* @author Jongho Moon
*
*/
public class Java6UnsafePluginClassLoaderTest {
@Test
public void test() throws Exception {
ClassLoader parent = ClassLoader.getSystemClassLoader();
ClassLoader child = new Java6UnsafePluginClassLoader(new URL[0], parent);
final int run = 10000;
final int threadNum = 16;
Thread[] thread = new Thread[threadNum];
for (int i = 0; i < threadNum; i++) {
if (i % 2 == 0) {
thread[i] = new Thread(new Parent(parent, child, run));
} else {
thread[i] = new Thread(new Child(child, run));
}
}
for (int i = 0; i < threadNum; i++) {
thread[i].start();
}
System.out.println("Wait workers...");
for (int i = 0; i < threadNum; i++) {
thread[i].join();
}
}
private static class Parent implements Runnable {
private final ClassLoader parent;
private final ClassLoader child;
private final int count;
public Parent(ClassLoader parent, ClassLoader child, int count) {
this.parent = parent;
this.child = child;
this.count = count;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
synchronized(parent) {
try {
child.loadClass("no.such.Class");
} catch (ClassNotFoundException e) {
// ignore
}
}
}
}
}
private static class Child implements Runnable {
private final ClassLoader child;
private final int count;
public Child(ClassLoader child, int count) {
this.child = child;
this.count = count;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
synchronized(child) {
try {
child.loadClass("no.such.Class");
} catch (ClassNotFoundException e) {
// ignore
}
}
}
}
}
}
+13 -1
View File
@@ -27,6 +27,7 @@ BASE_DIR=`dirname "$bin"`
CONF_DIR=$BASE_DIR/conf
HBASE_DIR=$BASE_DIR/hbase
DATA_DIR=$BASE_DIR/data
function func_check_hbase_installation
{
@@ -58,6 +59,13 @@ function func_download_hbase
fi
}
function delete_data_directory
{
if [ -d $DATA_DIR ]; then
rm -r $DATA_DIR
fi
}
function func_install_hbase
{
if [ ! -d $HBASE_DIR ]; then
@@ -71,8 +79,12 @@ function func_install_hbase
echo "Exiting"
exit 0
fi
delete_data_directory
tar xzf $HBASE_FILE
rm $HBASE_FILE
if [ -h hbase ]; then
unlink hbase
fi
ln -s $HBASE_VERSION hbase
cp $CONF_DIR/hbase/hbase-site.xml $HBASE_DIR/$HBASE_VERSION/conf/
chmod +x $HBASE_DIR/$HBASE_VERSION/bin/start-hbase.sh
@@ -92,4 +104,4 @@ function func_start_hbase
cd $CURRENT_DIR
}
func_start_hbase
func_start_hbase