Loading skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/assist/NoCocurrencyAceessObject.java +5 −4 Original line number Diff line number Diff line Loading @@ -5,14 +5,15 @@ import com.a.eye.skywalking.api.plugin.interceptor.InterceptorException; import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; /** * {@link NoCocurrencyAceessObject} is an abstract class, * works for class's methods call each others, which these methods should be intercepted. * {@link NoCocurrencyAceessObject} is method invocation counter, * when {@link #whenEnter(EnhancedClassInstanceContext, Runnable)}, counter + 1; * and when {@link #whenExist(EnhancedClassInstanceContext, Runnable)}, counter -1; * * At this scenario, only the first access should be intercepted. * When, and only when, the first enter and last exist, also meaning first access, the Runnable is called. * * @author wusheng */ public abstract class NoCocurrencyAceessObject implements InstanceMethodsAroundInterceptor { public class NoCocurrencyAceessObject { protected String invokeCounterKey = "__$invokeCounterKey"; protected Object invokeCounterInstLock = new Object(); Loading skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/loader/InterceptorInstanceLoader.java +47 −38 Original line number Diff line number Diff line package com.a.eye.skywalking.api.plugin.interceptor.loader; import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import com.a.eye.skywalking.api.plugin.interceptor.enhance.StaticMethodsAroundInterceptor; import com.a.eye.skywalking.logging.ILog; import com.a.eye.skywalking.logging.LogManager; import java.io.BufferedInputStream; Loading @@ -12,12 +15,16 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; /** * The Classloader controller. * This is a very important class in sky-walking's auto-instrumentation mechanism. * If you want to fully understand why need this, and how it works, you need have knowledge about Classloader appointment mechanism. * <p> * The <code>InterceptorInstanceLoader</code> is a classes finder and container. * * This is a very important class in sky-walking's auto-instrumentation mechanism. If you want to fully understand why * need this, and how it works, you need have knowledge about Classloader appointment mechanism. * * The loader will load a class, and focus the target class loader (be intercepted class's classloader) loads it. * <p> * * If the target class and target class loader are same, the loaded classes( {@link InstanceConstructorInterceptor}, * {@link InstanceMethodsAroundInterceptor} and {@link StaticMethodsAroundInterceptor} implementations) stay in singleton. * * Created by wusheng on 16/8/2. */ public class InterceptorInstanceLoader { Loading @@ -31,14 +38,10 @@ public class InterceptorInstanceLoader { throws InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException { String instanceKey = className + "_OF_" + targetClassLoader.getClass().getName() + "@" + Integer.toHexString(targetClassLoader.hashCode()); Object inst = INSTANCE_CACHE.get(instanceKey); if (inst != null) { return (T) inst; } if (inst == null) { if (InterceptorInstanceLoader.class.getClassLoader().equals(targetClassLoader)) { return (T) targetClassLoader.loadClass(className).newInstance(); } inst = targetClassLoader.loadClass(className).newInstance(); } else { instanceLoadLock.lock(); try { try { Loading @@ -49,15 +52,19 @@ public class InterceptorInstanceLoader { if (inst == null) { throw new ClassNotFoundException(targetClassLoader.toString() + " load interceptor class:" + className + " failure."); } INSTANCE_CACHE.put(instanceKey, inst); return (T) inst; } catch (Exception e) { throw new ClassNotFoundException(targetClassLoader.toString() + " load interceptor class:" + className + " failure.", e); } } finally { instanceLoadLock.unlock(); } } if (inst != null) { INSTANCE_CACHE.put(instanceKey, inst); } } return (T)inst; } /** Loading @@ -72,7 +79,8 @@ public class InterceptorInstanceLoader { * @throws IllegalAccessException * @throws InstantiationException */ private static <T> T loadBinary(String className, ClassLoader targetClassLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException { private static <T> T loadBinary(String className, ClassLoader targetClassLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException { String path = "/" + className.replace('.', '/').concat(".class"); byte[] data = null; BufferedInputStream is = null; Loading Loading @@ -111,21 +119,22 @@ public class InterceptorInstanceLoader { } } defineClassMethod.setAccessible(true); logger.debug("load binary code of {} to classload {}", className, targetClassLoader); logger.debug("load binary code of {} to classloader {}", className, targetClassLoader); Class<?> type = (Class<?>)defineClassMethod.invoke(targetClassLoader, className, data, 0, data.length, null); return (T)type.newInstance(); } /** * Find loaded class in the current classloader. * Just in case some classes have already been loaded for some reasons.s * Just in case some classes have already been loaded for some reason. * * @param className interceptor class name. * @param targetClassLoader the classloader, which should load the interceptor. * @param <T> * @return interceptor instance. */ private static <T> T findLoadedClass(String className, ClassLoader targetClassLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException { private static <T> T findLoadedClass(String className, ClassLoader targetClassLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException { Method defineClassMethod = null; Class<?> targetClassLoaderType = targetClassLoader.getClass(); while (defineClassMethod == null && targetClassLoaderType != null) { Loading skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/boot/ServiceManagerTest.java 0 → 100644 +17 −0 Original line number Diff line number Diff line package com.a.eye.skywalking.api.boot; import com.a.eye.skywalking.api.context.ContextManager; import org.junit.Assert; import org.junit.Test; /** * @author wusheng */ public class ServiceManagerTest { @Test public void testBoot() { ServiceManager.INSTANCE.boot(); ContextManager manager = ServiceManager.INSTANCE.findService(ContextManager.class); Assert.assertNotNull(manager); } } skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/plugin/assist/NoCocurrencyAceessObjectTest.java 0 → 100644 +46 −0 Original line number Diff line number Diff line package com.a.eye.skywalking.api.plugin.assist; import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; import com.a.eye.skywalking.api.plugin.interceptor.assist.NoCocurrencyAceessObject; import org.junit.Assert; import org.junit.Test; /** * @author wusheng */ public class NoCocurrencyAceessObjectTest { @Test public void testEntraExitCounter(){ NoCocurrencyAceessObject object = new NoCocurrencyAceessObject(); final EnhancedClassInstanceContext context = new EnhancedClassInstanceContext(); object.whenEnter(context, new Runnable() { @Override public void run() { context.set("firstEntrance", true); } }); object.whenEnter(context, new Runnable() { @Override public void run() { context.set("secondEntrance", true); } }); object.whenExist(context, new Runnable() { @Override public void run() { context.set("firstExit", true); } }); object.whenExist(context, new Runnable() { @Override public void run() { context.set("lastEntrance", true); } }); Assert.assertTrue(!context.isContain("secondEntrance")); Assert.assertTrue(!context.isContain("firstExit")); Assert.assertTrue(context.isContain("firstEntrance")); Assert.assertTrue(context.isContain("lastEntrance")); } } skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/plugin/interceptor/EnhancedClassInstanceContextTest.java 0 → 100644 +18 −0 Original line number Diff line number Diff line package com.a.eye.skywalking.api.plugin.interceptor; import org.junit.Assert; import org.junit.Test; /** * @author wusheng */ public class EnhancedClassInstanceContextTest { @Test public void test(){ EnhancedClassInstanceContext context = new EnhancedClassInstanceContext(); context.set("key", "value"); Assert.assertTrue(context.isContain("key")); Assert.assertEquals("value", context.get("key")); Assert.assertEquals("value", context.get("key", String.class)); } } Loading
skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/assist/NoCocurrencyAceessObject.java +5 −4 Original line number Diff line number Diff line Loading @@ -5,14 +5,15 @@ import com.a.eye.skywalking.api.plugin.interceptor.InterceptorException; import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; /** * {@link NoCocurrencyAceessObject} is an abstract class, * works for class's methods call each others, which these methods should be intercepted. * {@link NoCocurrencyAceessObject} is method invocation counter, * when {@link #whenEnter(EnhancedClassInstanceContext, Runnable)}, counter + 1; * and when {@link #whenExist(EnhancedClassInstanceContext, Runnable)}, counter -1; * * At this scenario, only the first access should be intercepted. * When, and only when, the first enter and last exist, also meaning first access, the Runnable is called. * * @author wusheng */ public abstract class NoCocurrencyAceessObject implements InstanceMethodsAroundInterceptor { public class NoCocurrencyAceessObject { protected String invokeCounterKey = "__$invokeCounterKey"; protected Object invokeCounterInstLock = new Object(); Loading
skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/loader/InterceptorInstanceLoader.java +47 −38 Original line number Diff line number Diff line package com.a.eye.skywalking.api.plugin.interceptor.loader; import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import com.a.eye.skywalking.api.plugin.interceptor.enhance.StaticMethodsAroundInterceptor; import com.a.eye.skywalking.logging.ILog; import com.a.eye.skywalking.logging.LogManager; import java.io.BufferedInputStream; Loading @@ -12,12 +15,16 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; /** * The Classloader controller. * This is a very important class in sky-walking's auto-instrumentation mechanism. * If you want to fully understand why need this, and how it works, you need have knowledge about Classloader appointment mechanism. * <p> * The <code>InterceptorInstanceLoader</code> is a classes finder and container. * * This is a very important class in sky-walking's auto-instrumentation mechanism. If you want to fully understand why * need this, and how it works, you need have knowledge about Classloader appointment mechanism. * * The loader will load a class, and focus the target class loader (be intercepted class's classloader) loads it. * <p> * * If the target class and target class loader are same, the loaded classes( {@link InstanceConstructorInterceptor}, * {@link InstanceMethodsAroundInterceptor} and {@link StaticMethodsAroundInterceptor} implementations) stay in singleton. * * Created by wusheng on 16/8/2. */ public class InterceptorInstanceLoader { Loading @@ -31,14 +38,10 @@ public class InterceptorInstanceLoader { throws InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException { String instanceKey = className + "_OF_" + targetClassLoader.getClass().getName() + "@" + Integer.toHexString(targetClassLoader.hashCode()); Object inst = INSTANCE_CACHE.get(instanceKey); if (inst != null) { return (T) inst; } if (inst == null) { if (InterceptorInstanceLoader.class.getClassLoader().equals(targetClassLoader)) { return (T) targetClassLoader.loadClass(className).newInstance(); } inst = targetClassLoader.loadClass(className).newInstance(); } else { instanceLoadLock.lock(); try { try { Loading @@ -49,15 +52,19 @@ public class InterceptorInstanceLoader { if (inst == null) { throw new ClassNotFoundException(targetClassLoader.toString() + " load interceptor class:" + className + " failure."); } INSTANCE_CACHE.put(instanceKey, inst); return (T) inst; } catch (Exception e) { throw new ClassNotFoundException(targetClassLoader.toString() + " load interceptor class:" + className + " failure.", e); } } finally { instanceLoadLock.unlock(); } } if (inst != null) { INSTANCE_CACHE.put(instanceKey, inst); } } return (T)inst; } /** Loading @@ -72,7 +79,8 @@ public class InterceptorInstanceLoader { * @throws IllegalAccessException * @throws InstantiationException */ private static <T> T loadBinary(String className, ClassLoader targetClassLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException { private static <T> T loadBinary(String className, ClassLoader targetClassLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException { String path = "/" + className.replace('.', '/').concat(".class"); byte[] data = null; BufferedInputStream is = null; Loading Loading @@ -111,21 +119,22 @@ public class InterceptorInstanceLoader { } } defineClassMethod.setAccessible(true); logger.debug("load binary code of {} to classload {}", className, targetClassLoader); logger.debug("load binary code of {} to classloader {}", className, targetClassLoader); Class<?> type = (Class<?>)defineClassMethod.invoke(targetClassLoader, className, data, 0, data.length, null); return (T)type.newInstance(); } /** * Find loaded class in the current classloader. * Just in case some classes have already been loaded for some reasons.s * Just in case some classes have already been loaded for some reason. * * @param className interceptor class name. * @param targetClassLoader the classloader, which should load the interceptor. * @param <T> * @return interceptor instance. */ private static <T> T findLoadedClass(String className, ClassLoader targetClassLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException { private static <T> T findLoadedClass(String className, ClassLoader targetClassLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException { Method defineClassMethod = null; Class<?> targetClassLoaderType = targetClassLoader.getClass(); while (defineClassMethod == null && targetClassLoaderType != null) { Loading
skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/boot/ServiceManagerTest.java 0 → 100644 +17 −0 Original line number Diff line number Diff line package com.a.eye.skywalking.api.boot; import com.a.eye.skywalking.api.context.ContextManager; import org.junit.Assert; import org.junit.Test; /** * @author wusheng */ public class ServiceManagerTest { @Test public void testBoot() { ServiceManager.INSTANCE.boot(); ContextManager manager = ServiceManager.INSTANCE.findService(ContextManager.class); Assert.assertNotNull(manager); } }
skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/plugin/assist/NoCocurrencyAceessObjectTest.java 0 → 100644 +46 −0 Original line number Diff line number Diff line package com.a.eye.skywalking.api.plugin.assist; import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; import com.a.eye.skywalking.api.plugin.interceptor.assist.NoCocurrencyAceessObject; import org.junit.Assert; import org.junit.Test; /** * @author wusheng */ public class NoCocurrencyAceessObjectTest { @Test public void testEntraExitCounter(){ NoCocurrencyAceessObject object = new NoCocurrencyAceessObject(); final EnhancedClassInstanceContext context = new EnhancedClassInstanceContext(); object.whenEnter(context, new Runnable() { @Override public void run() { context.set("firstEntrance", true); } }); object.whenEnter(context, new Runnable() { @Override public void run() { context.set("secondEntrance", true); } }); object.whenExist(context, new Runnable() { @Override public void run() { context.set("firstExit", true); } }); object.whenExist(context, new Runnable() { @Override public void run() { context.set("lastEntrance", true); } }); Assert.assertTrue(!context.isContain("secondEntrance")); Assert.assertTrue(!context.isContain("firstExit")); Assert.assertTrue(context.isContain("firstEntrance")); Assert.assertTrue(context.isContain("lastEntrance")); } }
skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/plugin/interceptor/EnhancedClassInstanceContextTest.java 0 → 100644 +18 −0 Original line number Diff line number Diff line package com.a.eye.skywalking.api.plugin.interceptor; import org.junit.Assert; import org.junit.Test; /** * @author wusheng */ public class EnhancedClassInstanceContextTest { @Test public void test(){ EnhancedClassInstanceContext context = new EnhancedClassInstanceContext(); context.set("key", "value"); Assert.assertTrue(context.isContain("key")); Assert.assertEquals("value", context.get("key")); Assert.assertEquals("value", context.get("key", String.class)); } }