diff --git a/agent-module/agent/src/main/resources/profiles/local/pinpoint.config b/agent-module/agent/src/main/resources/profiles/local/pinpoint.config index 78b2cb169763..f2470840ee29 100644 --- a/agent-module/agent/src/main/resources/profiles/local/pinpoint.config +++ b/agent-module/agent/src/main/resources/profiles/local/pinpoint.config @@ -32,6 +32,9 @@ profiler.application.namespace= profiler.interceptorregistry.size=65536 +# InterceptorHolder improves transform performance. +profiler.interceptor.holder.enable=true + # Manually override jvm vendor name (Oracle, IBM, OpenJDK, etc) # You probably won't ever need to set this value. profiler.jvm.vendor.name= diff --git a/agent-module/agent/src/main/resources/profiles/release/pinpoint.config b/agent-module/agent/src/main/resources/profiles/release/pinpoint.config index e709458a7800..509f2354e85a 100644 --- a/agent-module/agent/src/main/resources/profiles/release/pinpoint.config +++ b/agent-module/agent/src/main/resources/profiles/release/pinpoint.config @@ -31,6 +31,9 @@ profiler.application.namespace= profiler.interceptorregistry.size=8192 +# InterceptorHolder improves transform performance. +profiler.interceptor.holder.enable=true + # Manually override jvm vendor name (Oracle, IBM, OpenJDK, etc) # You probably won't ever need to set this value. profiler.jvm.vendor.name= diff --git a/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/DefaultInterceptorRegistryAdaptor.java b/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/DefaultInterceptorRegistryAdaptor.java index 9632b1e5e6e8..8865908a0ae4 100644 --- a/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/DefaultInterceptorRegistryAdaptor.java +++ b/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/DefaultInterceptorRegistryAdaptor.java @@ -30,21 +30,29 @@ public DefaultInterceptorRegistryAdaptor(int maxRegistrySize) { this.index = new WeakAtomicReferenceArray(maxRegistrySize, Interceptor.class); } - @Override public int addInterceptor(Interceptor interceptor) { if (interceptor == null) { return -1; } - final int newId = nextId(); - if (newId >= registrySize) { - throw new IndexOutOfBoundsException("Interceptor registry size exceeded. Check the \"profiler.interceptorregistry.size\" setting. size=" + index.length() + " id=" + id); - } + final int newId = checkMaxSize(nextId()); index.set(newId, interceptor); return newId; } + @Override + public int addInterceptor() { + return checkMaxSize(nextId()); + } + + private int checkMaxSize(int id) { + if (id >= registrySize) { + throw new IndexOutOfBoundsException("Interceptor registry size exceeded. Check the \"profiler.interceptorregistry.size\" setting. size=" + index.length() + " id=" + id); + } + return id; + } + private int nextId() { return id.getAndIncrement(); } diff --git a/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/EmptyRegistryAdaptor.java b/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/EmptyRegistryAdaptor.java index 3750dffd86a5..1c3cfa7d0a69 100644 --- a/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/EmptyRegistryAdaptor.java +++ b/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/EmptyRegistryAdaptor.java @@ -32,6 +32,11 @@ public EmptyRegistryAdaptor() { } + @Override + public int addInterceptor() { + return 0; + } + @Override public int addInterceptor(Interceptor interceptor) { return -1; diff --git a/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/InterceptorRegistry.java b/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/InterceptorRegistry.java index d3a910c542fe..dbaed1df11f1 100644 --- a/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/InterceptorRegistry.java +++ b/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/InterceptorRegistry.java @@ -32,6 +32,8 @@ public final class InterceptorRegistry { private static final AtomicReference REGISTRY = new AtomicReference<>(EmptyRegistryAdaptor.EMPTY); + private static boolean interceptorHolderEnable = true; + public static void bind(final InterceptorRegistryAdaptor interceptorRegistryAdaptor, final Object lock) { Objects.requireNonNull(interceptorRegistryAdaptor, "interceptorRegistryAdaptor"); @@ -53,4 +55,12 @@ public static void unbind(final Object lock) { public static Interceptor getInterceptor(int key) { return REGISTRY.get().getInterceptor(key); } + + public static void setInterceptorHolderEnable(boolean enable) { + interceptorHolderEnable = enable; + } + + public static boolean isInterceptorHolderEnable() { + return interceptorHolderEnable; + } } diff --git a/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/InterceptorRegistryAdaptor.java b/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/InterceptorRegistryAdaptor.java index 75189b4f892a..66fab5c53ff3 100644 --- a/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/InterceptorRegistryAdaptor.java +++ b/agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/interceptor/registry/InterceptorRegistryAdaptor.java @@ -7,7 +7,10 @@ * @author emeroad */ public interface InterceptorRegistryAdaptor { + int addInterceptor(); + int addInterceptor(Interceptor interceptor); + Interceptor getInterceptor(int key); void clear(); diff --git a/agent-module/bootstraps/bootstrap-core/src/test/java/com/navercorp/pinpoint/bootstrap/interceptor/DefaultInterceptorRegistryAdaptorTest.java b/agent-module/bootstraps/bootstrap-core/src/test/java/com/navercorp/pinpoint/bootstrap/interceptor/DefaultInterceptorRegistryAdaptorTest.java index 1a8aff021b85..1718616ea27b 100644 --- a/agent-module/bootstraps/bootstrap-core/src/test/java/com/navercorp/pinpoint/bootstrap/interceptor/DefaultInterceptorRegistryAdaptorTest.java +++ b/agent-module/bootstraps/bootstrap-core/src/test/java/com/navercorp/pinpoint/bootstrap/interceptor/DefaultInterceptorRegistryAdaptorTest.java @@ -58,4 +58,10 @@ public void addSimpleInterceptor() { Assertions.assertSame(mock, find); } + + @Test + public void addInterceptor() { + InterceptorRegistryAdaptor registry = new DefaultInterceptorRegistryAdaptor(); + int key = registry.addInterceptor(); + } } \ No newline at end of file diff --git a/agent-module/profiler-optional/profiler-optional-jdk8/src/test/java/com/navercorp/test/pinpoint/jdk8/interfaces/MethodInterfaceTest.java b/agent-module/profiler-optional/profiler-optional-jdk8/src/test/java/com/navercorp/test/pinpoint/jdk8/interfaces/MethodInterfaceTest.java index 7711e66e9305..0d3d6ac7003c 100644 --- a/agent-module/profiler-optional/profiler-optional-jdk8/src/test/java/com/navercorp/test/pinpoint/jdk8/interfaces/MethodInterfaceTest.java +++ b/agent-module/profiler-optional/profiler-optional-jdk8/src/test/java/com/navercorp/test/pinpoint/jdk8/interfaces/MethodInterfaceTest.java @@ -17,22 +17,21 @@ package com.navercorp.test.pinpoint.jdk8.interfaces; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentContext; +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; +import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; import com.navercorp.pinpoint.profiler.instrument.ASMClass; import com.navercorp.pinpoint.profiler.instrument.ASMClassNodeAdapter; import com.navercorp.pinpoint.profiler.instrument.ASMClassWriter; import com.navercorp.pinpoint.profiler.instrument.ASMFieldNodeAdapter; +import com.navercorp.pinpoint.profiler.instrument.ASMInterceptorHolder; import com.navercorp.pinpoint.profiler.instrument.ASMMethodNodeAdapter; import com.navercorp.pinpoint.profiler.instrument.EngineComponent; import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorDefinition; import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorDefinitionFactory; -import com.navercorp.pinpoint.profiler.interceptor.registry.DefaultInterceptorRegistryBinder; -import com.navercorp.pinpoint.profiler.interceptor.registry.InterceptorRegistryBinder; import com.navercorp.pinpoint.profiler.util.JavaAssistUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; @@ -47,6 +46,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; @@ -55,28 +55,18 @@ * @author jaehong.kim */ public class MethodInterfaceTest { - private final static InterceptorRegistryBinder interceptorRegistryBinder = new DefaultInterceptorRegistryBinder(); private final static InstrumentContext pluginContext = mock(InstrumentContext.class); + private AtomicInteger interceptorIdCounter = new AtomicInteger(); private final Logger logger = LogManager.getLogger(this.getClass()); - @BeforeAll - public static void beforeClass() { - interceptorRegistryBinder.bind(); - } - - @AfterAll - public static void afterClass() { - interceptorRegistryBinder.unbind(); - } - @Test public void addInterceptor() throws Exception { final String targetInterfaceName = "com.navercorp.test.pinpoint.jdk8.interfaces.MethodInterface"; final String targetClassName = "com.navercorp.test.pinpoint.jdk8.interfaces.MethodInterfaceClass"; logger.debug("Add interceptor interface={}, class={}", targetInterfaceName, targetClassName); - final int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new SimpleInterceptor()); + final Interceptor interceptor = new SimpleInterceptor(); final InterceptorDefinition interceptorDefinition = new InterceptorDefinitionFactory().createInterceptorDefinition(SimpleInterceptor.class); final List methodNameList = Arrays.asList("currentTimeMillis", "foo"); TestClassLoader classLoader = new TestClassLoader(); @@ -100,6 +90,13 @@ public void handle(ClassNode classNode) { if (!methodNameList.contains(methodNode.name)) { continue; } + int interceptorId = interceptorIdCounter.incrementAndGet(); + try { + ASMInterceptorHolder.create(interceptorId, classLoader, interceptor); + } catch (InstrumentException e) { + throw new RuntimeException(e); + } + methodNodeAdapter.addBeforeInterceptor(interceptorId, interceptorDefinition, 99); logger.debug("Add before interceptor in method={}", methodNode.name); methodNodeAdapter.addAfterInterceptor(interceptorId, interceptorDefinition, 99); diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/provider/InterceptorRegistryBinderProvider.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/provider/InterceptorRegistryBinderProvider.java index 303c3054ad5b..461a2a41eb13 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/provider/InterceptorRegistryBinderProvider.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/provider/InterceptorRegistryBinderProvider.java @@ -28,13 +28,13 @@ /** * @author Woonduk Kang(emeroad) */ -public class InterceptorRegistryBinderProvider implements Provider { +public class InterceptorRegistryBinderProvider implements Provider { private final InterceptorRegistryBinder interceptorRegistryBinder; @Inject public InterceptorRegistryBinderProvider(InstrumentConfig instrumentConfig) { - this(getInterceptorRegistrySize(instrumentConfig)); + this(getInterceptorRegistrySize(instrumentConfig), getInterceptorHolderEnable(instrumentConfig)); } private static int getInterceptorRegistrySize(InstrumentConfig instrumentConfig) { @@ -42,8 +42,13 @@ private static int getInterceptorRegistrySize(InstrumentConfig instrumentConfig) return instrumentConfig.getInterceptorRegistrySize(); } - public InterceptorRegistryBinderProvider(int interceptorSize) { - this.interceptorRegistryBinder = new DefaultInterceptorRegistryBinder(interceptorSize); + private static boolean getInterceptorHolderEnable(InstrumentConfig instrumentConfig) { + Objects.requireNonNull(instrumentConfig, "instrumentConfig"); + return instrumentConfig.getInterceptorHolderEnable(); + } + + public InterceptorRegistryBinderProvider(int interceptorSize, boolean interceptorHolderEnable) { + this.interceptorRegistryBinder = new DefaultInterceptorRegistryBinder(interceptorSize, interceptorHolderEnable); } @Override diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMClass.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMClass.java index 553c9a57dc13..dd04417a67e7 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMClass.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMClass.java @@ -431,7 +431,7 @@ private int addInterceptor0(TargetFilter annotation, Class interceptorClass, Object[] providedArguments, ScopeInfo scopeInfo, MethodDescriptor methodDescriptor) throws InstrumentException { + Builder builder = new Builder(interceptorId); + builder.interceptorFactory(classLoader, interceptorFactory, interceptorClass, providedArguments, scopeInfo, methodDescriptor); + builder.build(); + } + + // for test + public static void create(int interceptorId, ClassLoader classLoader, Interceptor interceptor) throws InstrumentException { + Builder builder = new Builder(interceptorId); + builder.interceptor(classLoader, interceptor); + builder.build(); + } + + private final String className; + private final String innerClassName; + + public ASMInterceptorHolder(int interceptorId) { + this.className = getInterceptorHolderClassName(interceptorId); + this.innerClassName = this.className + "$LazyLoading"; + } + + public Class loadInterceptorClass(ClassLoader classLoader) throws InstrumentException { + if (classLoader == null) { + throw new InstrumentException("classLoader must not be null"); + } + + try { + final Class clazz = classLoader.loadClass(className); + if (clazz == null) { + // defense code + throw new InstrumentException("not found interceptorHolderClass, className=" + className); + } + + final Method method = clazz.getDeclaredMethod("get"); + final Object o = method.invoke(null); + if (o instanceof Interceptor) { + return (Class) o.getClass(); + } else { + throw new InstrumentException("not found interceptor, className=" + className); + } + } catch (ClassNotFoundException e) { + throw new InstrumentException("not found class, className=" + className, e); + } catch (InvocationTargetException e) { + throw new InstrumentException("invocation fail, className=" + className, e); + } catch (NoSuchMethodException e) { + throw new InstrumentException("not found 'get' method, className=" + className, e); + } catch (IllegalAccessException e) { + throw new InstrumentException("access fail, className=" + className, e); + } + } + + public void init(Class interceptorHolderClass, InterceptorFactory factory, Class interceptorClass, Object[] providedArguments, ScopeInfo scopeInfo, MethodDescriptor methodDescriptor) throws InstrumentException { + init(interceptorHolderClass, new InterceptorLazyLoadingSupplier(factory, interceptorClass, providedArguments, scopeInfo, methodDescriptor)); + } + + public void init(Class interceptorHolderClass, Interceptor interceptor) throws InstrumentException { + init(interceptorHolderClass, new InterceptorSupplier(interceptor)); + } + + private void init(Class interceptorHolderClass, Supplier supplier) throws InstrumentException { + try { + final Method method = interceptorHolderClass.getDeclaredMethod("set", Supplier.class); + method.invoke(null, supplier); + } catch (NoSuchMethodException e) { + throw new InstrumentException("not found 'set' method, className=" + interceptorHolderClass.getName(), e); + } catch (IllegalAccessException e) { + throw new InstrumentException("access fail, className=" + interceptorHolderClass.getName(), e); + } catch (InvocationTargetException e) { + throw new InstrumentException("invocation fail, className=" + interceptorHolderClass.getName(), e); + } + } + + public Class defineClass(ClassLoader classLoader) throws InstrumentException { + try { + final byte[] mainClassBytes = toMainClassByteArray(); + final Class mainClass = InterceptorDefineClassHelper.defineClass(classLoader, className, mainClassBytes); + final byte[] innerClassByte = toInnerClassByteArray(); + InterceptorDefineClassHelper.defineClass(classLoader, innerClassName, innerClassByte); + return mainClass; + } catch (Exception e) { + throw new InstrumentException("defineClass fail", e); + } + } + + byte[] toMainClassByteArray() throws InstrumentException { + try { + ClassNode classNode = readClass(INTERCEPTOR_HOLDER_CLASS); + final ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + final ClassVisitor renameClassAdapter = new RenameClassAdapter(classWriter, className); + classNode.accept(renameClassAdapter); + return classWriter.toByteArray(); + } catch (IOException e) { + // read fail + throw new InstrumentException("ClassReader fail, classFile=" + INTERCEPTOR_HOLDER_CLASS, e); + } + } + + byte[] toInnerClassByteArray() throws InstrumentException { + try { + ClassNode classNode = readClass(INTERCEPTOR_HOLDER_INNER_CLASS); + final ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + final ClassVisitor renameClassAdapter = new RenameInnerClassAdapter(classWriter, className); + classNode.accept(renameClassAdapter); + return classWriter.toByteArray(); + } catch (IOException e) { + // read fail + throw new InstrumentException("ClassReader fail, classFile=" + INTERCEPTOR_HOLDER_INNER_CLASS, e); + } + } + + ClassNode readClass(String classFileName) throws IOException { + final ClassLoader classLoader = ASMInterceptorHolder.class.getClassLoader(); + final InputStream inputStram = classLoader.getResourceAsStream(classFileName); + if (inputStram == null) { + // defense code + throw new IOException("not found class " + classFileName); + } + + try { + final ClassReader classReader = new ClassReader(inputStram); + ClassNode classNode = new ClassNode(); + classReader.accept(classNode, 0); + return classNode; + } finally { + inputStram.close(); + } + } + + static class Builder { + private final int interceptorId; + private ClassLoader classLoader; + private InterceptorFactory interceptorFactory; + private Class interceptorClass; + private Object[] providedArguments; + private ScopeInfo scopeInfo; + private MethodDescriptor methodDescriptor; + private Interceptor interceptor; + + public Builder(int interceptorId) { + this.interceptorId = interceptorId; + } + + public Builder interceptorFactory(ClassLoader classLoader, InterceptorFactory interceptorFactory, Class interceptorClass, Object[] providedArguments, ScopeInfo scopeInfo, MethodDescriptor methodDescriptor) { + this.classLoader = Objects.requireNonNull(classLoader, "classLoader"); + this.interceptorFactory = Objects.requireNonNull(interceptorFactory, "interceptorFactory"); + this.interceptorClass = Objects.requireNonNull(interceptorClass, "interceptorClass"); + this.providedArguments = providedArguments; + this.scopeInfo = scopeInfo; + this.methodDescriptor = methodDescriptor; + return this; + } + + public Builder interceptor(ClassLoader classLoader, Interceptor interceptor) { + this.classLoader = Objects.requireNonNull(classLoader, "classLoader"); + this.interceptor = Objects.requireNonNull(interceptor, "interceptor"); + return this; + } + + public ASMInterceptorHolder build() throws InstrumentException { + final ASMInterceptorHolder holder = new ASMInterceptorHolder(interceptorId); + final Class clazz = holder.defineClass(classLoader); + // exception handling. + if (interceptor != null) { + holder.init(clazz, interceptor); + } else if (interceptorFactory != null) { + holder.init(clazz, interceptorFactory, interceptorClass, providedArguments, scopeInfo, methodDescriptor); + } else { + throw new InstrumentException("either interceptor or interceptorFactory must be present."); + } + return holder; + } + } + + class RenameClassAdapter extends ClassVisitor { + private final String newInternalName; + + public RenameClassAdapter(ClassVisitor classVisitor, String name) { + super(ASMVersion.VERSION, classVisitor); + this.newInternalName = JavaAssistUtils.javaNameToJvmName(name); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, this.newInternalName, signature, superName, interfaces); + } + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + super.visitInnerClass(newInternalName + "$" + innerName, newInternalName, innerName, access); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + if (name.equals("")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { + // LOCALVARIABLE this Lcom/navercorp/pinpoint/profiler/instrument/mock/InterceptorHolder; L0 L1 0 + if (name.equals("this")) { + final String newDescriptor = "L" + newInternalName + ";"; + super.visitLocalVariable(name, newDescriptor, signature, start, end, index); + } else { + super.visitLocalVariable(name, descriptor, signature, start, end, index); + } + } + }; + } else if (name.equals("get")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + // GETSTATIC com/navercorp/pinpoint/profiler/instrument/mock/InterceptorHolder.holder : Lcom/navercorp/pinpoint/bootstrap/interceptor/Interceptor; + final int innerNameStartPosition = owner.indexOf('$'); + if (innerNameStartPosition != -1) { + final String innerName = owner.substring(innerNameStartPosition); + super.visitFieldInsn(opcode, newInternalName + innerName, name, descriptor); + } else { + super.visitFieldInsn(opcode, newInternalName, name, descriptor); + } + } + }; + } else if (name.equals("set")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + // PUTSTATIC com/navercorp/pinpoint/profiler/instrument/mock/InterceptorBinder.binder : Lcom/navercorp/pinpoint/bootstrap/interceptor/Interceptor; + super.visitFieldInsn(opcode, newInternalName, name, descriptor); + } + }; + } else if (name.equals("access$000")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + // GETSTATIC com/navercorp/pinpoint/profiler/instrument/mock/InterceptorBinder.factory : Lcom/navercorp/pinpoint/profiler/instrument/mock/InterceptorLazyFactory; + super.visitFieldInsn(opcode, newInternalName, name, descriptor); + } + }; + } + + return super.visitMethod(access, name, descriptor, signature, exceptions); + } + } + + class RenameInnerClassAdapter extends ClassVisitor { + private final String newInternalName; + + public RenameInnerClassAdapter(ClassVisitor classVisitor, String name) { + super(ASMVersion.VERSION, classVisitor); + this.newInternalName = JavaAssistUtils.javaNameToJvmName(name); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + final int innerNameStartPosition = name.indexOf('$'); + if (innerNameStartPosition != -1) { + final String innerName = name.substring(innerNameStartPosition); + super.visit(version, access, this.newInternalName + innerName, signature, superName, interfaces); + } else { + super.visit(version, access, this.newInternalName, signature, superName, interfaces); + } + } + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + super.visitInnerClass(newInternalName + "$" + innerName, newInternalName, innerName, access); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + if (name.equals("")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { + // LOCALVARIABLE this Lcom/navercorp/pinpoint/profiler/instrument/mock/InterceptorHolder; L0 L1 0 + if (name.equals("this")) { + final int innerNameStartPosition = descriptor.indexOf('$'); + if (innerNameStartPosition != -1) { + final String innerName = descriptor.substring(innerNameStartPosition); + final String newDescriptor = "L" + newInternalName + innerName; + super.visitLocalVariable(name, newDescriptor, signature, start, end, index); + } else { + super.visitLocalVariable(name, descriptor, signature, start, end, index); + } + } else { + super.visitLocalVariable(name, descriptor, signature, start, end, index); + } + } + }; + } else if (name.equals("")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { + if (name.equals("access$000")) { + super.visitMethodInsn(opcode, newInternalName, name, descriptor, isInterface); + } else { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + } + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + // GETSTATIC com/navercorp/pinpoint/profiler/instrument/mock/InterceptorHolder.holder : Lcom/navercorp/pinpoint/bootstrap/interceptor/Interceptor; + final int innerNameStartPosition = owner.indexOf('$'); + if (innerNameStartPosition != -1) { + final String innerName = owner.substring(innerNameStartPosition); + super.visitFieldInsn(opcode, newInternalName + innerName, name, descriptor); + } else { + super.visitFieldInsn(opcode, newInternalName, name, descriptor); + } + } + }; + } + + return super.visitMethod(access, name, descriptor, signature, exceptions); + } + } +} diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMMethod.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMMethod.java index fc6d82205c14..d4e34c199f2d 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMMethod.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMMethod.java @@ -52,7 +52,6 @@ public class ASMMethod implements InstrumentMethod { public ASMMethod(EngineComponent engineComponent, InstrumentContext pluginContext, ASMClass declaringClass, MethodNode methodNode) { this(engineComponent, pluginContext, declaringClass, new ASMMethodNodeAdapter(JavaAssistUtils.javaNameToJvmName(declaringClass.getName()), methodNode)); - } public ASMMethod(EngineComponent engineComponent, InstrumentContext pluginContext, ASMClass declaringClass, ASMMethodNodeAdapter methodNode) { @@ -64,8 +63,7 @@ public ASMMethod(EngineComponent engineComponent, InstrumentContext pluginContex final String[] parameterVariableNames = this.methodNode.getParameterNames(); final int lineNumber = this.methodNode.getLineNumber(); - this.descriptor = new DefaultMethodDescriptor(declaringClass.getName(), methodNode.getName(), - getParameterTypes(), parameterVariableNames, lineNumber); + this.descriptor = new DefaultMethodDescriptor(declaringClass.getName(), methodNode.getName(), getParameterTypes(), parameterVariableNames, lineNumber); } @Override @@ -107,103 +105,14 @@ public Class loadInterceptorClass(String interceptorClass } } - @Override - public void addInterceptor(int interceptorId) throws InstrumentException { - final Interceptor interceptor = InterceptorRegistry.getInterceptor(interceptorId); - try { - addInterceptor0(interceptor, interceptorId); - } catch (Exception e) { - throw new InstrumentException("Failed to add interceptor " + interceptor.getClass().getName() + " to " + this.methodNode.getLongName(), e); - } - } - - // for internal api - int addInterceptorInternal(Class interceptorClass, Object[] constructorArgs, InterceptorScope interceptorScope, ExecutionPolicy executionPolicy) throws InstrumentException { - Objects.requireNonNull(interceptorClass, "interceptorClass"); - - final Interceptor interceptor = newInterceptor(interceptorClass, constructorArgs, interceptorScope, executionPolicy); - return addInterceptor0(interceptor); - } - - private int addInterceptor0(Interceptor interceptor) { - final int interceptorId = this.engineComponent.addInterceptor(interceptor); - - addInterceptor0(interceptor, interceptorId); - return interceptorId; - } - - private Interceptor newInterceptor(Class interceptorClass, Object[] constructorArgs, InterceptorScope interceptorScope, ExecutionPolicy executionPolicy) { - final ScopeFactory scopeFactory = this.engineComponent.getScopeFactory(); - - final ScopeInfo scopeInfo = scopeFactory.newScopeInfo(pluginContext, interceptorClass, interceptorScope, executionPolicy); - return createInterceptor(interceptorClass, constructorArgs, scopeInfo); - } - - - private Interceptor createInterceptor(Class interceptorClass, Object[] constructorArgs, ScopeInfo scopeInfo) { - // exception handling. - ObjectBinderFactory objectBinderFactory = this.engineComponent.getObjectBinderFactory(); - final AnnotatedInterceptorFactory factory = objectBinderFactory.newAnnotatedInterceptorFactory(this.pluginContext); - final Interceptor interceptor = factory.newInterceptor(interceptorClass, constructorArgs, scopeInfo, this.declaringClass, this); - return interceptor; - } - - private void addInterceptor0(Interceptor interceptor, int interceptorId) { - Objects.requireNonNull(interceptor, "interceptor"); - - final InterceptorDefinition interceptorDefinition = this.engineComponent.createInterceptorDefinition(interceptor.getClass()); - final Class interceptorClass = interceptorDefinition.getInterceptorClass(); - final CaptureType captureType = interceptorDefinition.getCaptureType(); - if (this.methodNode.hasInterceptor()) { - logger.warn("Skip adding interceptor. 'already intercepted method' class={}, interceptor={}", this.declaringClass.getName(), interceptorClass.getName()); - return; - } - - if (this.methodNode.isAbstract() || this.methodNode.isNative()) { - logger.info("Skip adding interceptor. 'abstract or native method' class={}, interceptor={}", this.declaringClass.getName(), interceptorClass.getName()); - return; - } - - int apiId = -1; - if (interceptorDefinition.getInterceptorType() == InterceptorType.API_ID_AWARE) { - apiId = this.engineComponent.cacheApi(this.descriptor); - } - - // add before interceptor. - if (isBeforeInterceptor(captureType) && interceptorDefinition.getBeforeMethod() != null) { - this.methodNode.addBeforeInterceptor(interceptorId, interceptorDefinition, apiId); - this.declaringClass.setModified(true); - } else { - if (isDebug) { - logger.debug("Skip adding before interceptorDefinition because the interceptorDefinition doesn't have before method: {}", interceptorClass.getName()); - } - } - - // add after interface. - if (isAfterInterceptor(captureType) && interceptorDefinition.getAfterMethod() != null) { - this.methodNode.addAfterInterceptor(interceptorId, interceptorDefinition, apiId); - this.declaringClass.setModified(true); - } else { - if (isDebug) { - logger.debug("Skip adding after interceptor because the interceptor doesn't have after method: {}", interceptorClass.getName()); - } - } - } - - private boolean isBeforeInterceptor(CaptureType captureType) { - return CaptureType.BEFORE == captureType || CaptureType.AROUND == captureType; - } - - private boolean isAfterInterceptor(CaptureType captureType) { - return CaptureType.AFTER == captureType || CaptureType.AROUND == captureType; - } @Override public int addInterceptor(Class interceptorClass) throws InstrumentException { Objects.requireNonNull(interceptorClass, "interceptorClass"); - final Interceptor interceptor = newInterceptor(interceptorClass, null, null, null); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, null, null, null); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; } @Override @@ -211,19 +120,20 @@ public int addInterceptor(Class interceptorClass, Object[ Objects.requireNonNull(interceptorClass, "interceptorClass"); Objects.requireNonNull(constructorArgs, "constructorArgs"); - final Interceptor interceptor = newInterceptor(interceptorClass, constructorArgs, null, null); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, constructorArgs, null, null); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; } - @Override public int addScopedInterceptor(Class interceptorClass, String scopeName) throws InstrumentException { Objects.requireNonNull(interceptorClass, "interceptorClass"); Objects.requireNonNull(scopeName, "scopeName"); final InterceptorScope interceptorScope = this.pluginContext.getInterceptorScope(scopeName); - final Interceptor interceptor = newInterceptor(interceptorClass, null, interceptorScope, null); - return addInterceptor0(interceptor); + final int interceptor = newInterceptor(interceptorClass, null, interceptorScope, null); + addInterceptor0(interceptorClass, interceptor); + return interceptor; } @Override @@ -231,8 +141,9 @@ public int addScopedInterceptor(Class interceptorClass, I Objects.requireNonNull(interceptorClass, "interceptorClass"); Objects.requireNonNull(interceptorScope, "interceptorScope"); - final Interceptor interceptor = newInterceptor(interceptorClass, null, interceptorScope, null); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, null, interceptorScope, null); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; } @Override @@ -242,8 +153,9 @@ public int addScopedInterceptor(Class interceptorClass, S Objects.requireNonNull(executionPolicy, "executionPolicy"); final InterceptorScope interceptorScope = this.pluginContext.getInterceptorScope(scopeName); - final Interceptor interceptor = newInterceptor(interceptorClass, null, interceptorScope, executionPolicy); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, null, interceptorScope, executionPolicy); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; } @Override @@ -252,8 +164,9 @@ public int addScopedInterceptor(Class interceptorClass, I Objects.requireNonNull(interceptorScope, "interceptorScope"); Objects.requireNonNull(executionPolicy, "executionPolicy"); - final Interceptor interceptor = newInterceptor(interceptorClass, null, interceptorScope, executionPolicy); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, null, interceptorScope, executionPolicy); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; } @Override @@ -263,8 +176,9 @@ public int addScopedInterceptor(Class interceptorClass, O Objects.requireNonNull(scopeName, "scopeName"); final InterceptorScope interceptorScope = this.pluginContext.getInterceptorScope(scopeName); - final Interceptor interceptor = newInterceptor(interceptorClass, constructorArgs, interceptorScope, null); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, constructorArgs, interceptorScope, null); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; } @Override @@ -273,8 +187,9 @@ public int addScopedInterceptor(Class interceptorClass, O Objects.requireNonNull(constructorArgs, "constructorArgs"); Objects.requireNonNull(interceptorScope, "interceptorScope"); - final Interceptor interceptor = newInterceptor(interceptorClass, constructorArgs, interceptorScope, null); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, constructorArgs, interceptorScope, null); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; } @Override @@ -285,8 +200,9 @@ public int addScopedInterceptor(Class interceptorClass, O Objects.requireNonNull(executionPolicy, "executionPolicy"); final InterceptorScope interceptorScope = this.pluginContext.getInterceptorScope(scopeName); - final Interceptor interceptor = newInterceptor(interceptorClass, constructorArgs, interceptorScope, executionPolicy); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, constructorArgs, interceptorScope, executionPolicy); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; } @Override @@ -296,9 +212,106 @@ public int addScopedInterceptor(Class interceptorClass, O Objects.requireNonNull(interceptorScope, "interceptorScope"); Objects.requireNonNull(executionPolicy, "executionPolicy"); - final Interceptor interceptor = newInterceptor(interceptorClass, constructorArgs, interceptorScope, executionPolicy); - return addInterceptor0(interceptor); + final int interceptorId = newInterceptor(interceptorClass, constructorArgs, interceptorScope, executionPolicy); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; + } + + @Override + public void addInterceptor(int interceptorId) throws InstrumentException { + if (InterceptorRegistry.isInterceptorHolderEnable()) { + final ASMInterceptorHolder holder = new ASMInterceptorHolder(interceptorId); + final Class interceptorClass = holder.loadInterceptorClass(this.declaringClass.getClassLoader()); + addInterceptor0(interceptorClass, interceptorId); + } else { + final Interceptor interceptor = InterceptorRegistry.getInterceptor(interceptorId); + if (interceptor == null) { + // defense code + throw new InstrumentException("not found interceptor " + interceptor.getClass().getName() + " to " + this.methodNode.getLongName()); + } + try { + addInterceptor0(interceptor.getClass(), interceptorId); + } catch (Exception e) { + throw new InstrumentException("add interceptor0 " + interceptor.getClass().getName() + " to " + this.methodNode.getLongName(), e); + } + } + } + + // for internal api + int addInterceptorInternal(Class interceptorClass, Object[] constructorArgs, InterceptorScope interceptorScope, ExecutionPolicy executionPolicy) throws InstrumentException { + Objects.requireNonNull(interceptorClass, "interceptorClass"); + + final int interceptorId = newInterceptor(interceptorClass, constructorArgs, interceptorScope, executionPolicy); + addInterceptor0(interceptorClass, interceptorId); + return interceptorId; + } + + private int newInterceptor(Class interceptorClass, Object[] constructorArgs, InterceptorScope interceptorScope, ExecutionPolicy executionPolicy) throws InstrumentException { + final ScopeFactory scopeFactory = this.engineComponent.getScopeFactory(); + final ScopeInfo scopeInfo = scopeFactory.newScopeInfo(pluginContext, interceptorClass, interceptorScope, executionPolicy); + return createInterceptor(interceptorClass, constructorArgs, scopeInfo); + } + + private int createInterceptor(Class interceptorClass, Object[] constructorArgs, ScopeInfo scopeInfo) throws InstrumentException { + final ObjectBinderFactory objectBinderFactory = this.engineComponent.getObjectBinderFactory(); + final AnnotatedInterceptorFactory factory = objectBinderFactory.newAnnotatedInterceptorFactory(this.pluginContext); + int interceptorId = 0; + if (InterceptorRegistry.isInterceptorHolderEnable()) { + interceptorId = this.engineComponent.addInterceptor(); + ASMInterceptorHolder.create(interceptorId, this.declaringClass.getClassLoader(), factory, interceptorClass, constructorArgs, scopeInfo, this.descriptor); + } else { + final Interceptor interceptor = factory.newInterceptor(interceptorClass, constructorArgs, scopeInfo, this.descriptor); + interceptorId = this.engineComponent.addInterceptor(interceptor); + } + return interceptorId; + } + + private void addInterceptor0(Class interceptorClass, int interceptorId) { + Objects.requireNonNull(interceptorClass, "interceptorClass"); + + final InterceptorDefinition interceptorDefinition = this.engineComponent.createInterceptorDefinition(interceptorClass); + final CaptureType captureType = interceptorDefinition.getCaptureType(); + if (this.methodNode.hasInterceptor()) { + logger.warn("Skip adding interceptor. 'already intercepted method' class={}, interceptor={}", this.declaringClass.getName(), interceptorClass.getName()); + return; + } + + if (this.methodNode.isAbstract() || this.methodNode.isNative()) { + logger.info("Skip adding interceptor. 'abstract or native method' class={}, interceptor={}", this.declaringClass.getName(), interceptorClass.getName()); + return; + } + + int apiId = 0; + if (interceptorDefinition.getInterceptorType() == InterceptorType.API_ID_AWARE) { + apiId = this.engineComponent.cacheApi(this.descriptor); + } + + // add before interceptor. + if (isBeforeInterceptor(captureType) && interceptorDefinition.getBeforeMethod() != null) { + this.methodNode.addBeforeInterceptor(interceptorId, interceptorDefinition, apiId); + this.declaringClass.setModified(true); + } else { + if (isDebug) { + logger.debug("Skip adding before interceptorDefinition because the interceptorDefinition doesn't have before method: {}", interceptorClass.getName()); + } + } + + // add after interface. + if (isAfterInterceptor(captureType) && interceptorDefinition.getAfterMethod() != null) { + this.methodNode.addAfterInterceptor(interceptorId, interceptorDefinition, apiId); + this.declaringClass.setModified(true); + } else { + if (isDebug) { + logger.debug("Skip adding after interceptor because the interceptor doesn't have after method: {}", interceptorClass.getName()); + } + } } + private boolean isBeforeInterceptor(CaptureType captureType) { + return CaptureType.BEFORE == captureType || CaptureType.AROUND == captureType; + } + private boolean isAfterInterceptor(CaptureType captureType) { + return CaptureType.AFTER == captureType || CaptureType.AROUND == captureType; + } } \ No newline at end of file diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodVariables.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodVariables.java index bbc20a15d701..3d92828d75a3 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodVariables.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodVariables.java @@ -192,7 +192,7 @@ public void initLocalVariables(final InsnList instructions) { // find enter & exit instruction. final LabelNode variableStartLabelNode = new LabelNode(); final LabelNode variableEndLabelNode = new LabelNode(); - if(instructions.getFirst() != null) { + if (instructions.getFirst() != null) { instructions.insertBefore(instructions.getFirst(), variableStartLabelNode); } else { instructions.insert(variableStartLabelNode); @@ -298,8 +298,13 @@ AbstractInsnNode findInitConstructorInstruction() { private void initInterceptorVar(final InsnList instructions, final int interceptorId) { assertInitializedInterceptorLocalVariables(); this.interceptorVarIndex = addInterceptorLocalVariable("_$PINPOINT$_interceptor", "Lcom/navercorp/pinpoint/bootstrap/interceptor/Interceptor;"); - push(instructions, interceptorId); - instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(InterceptorRegistry.class), "getInterceptor", "(I)" + Type.getDescriptor(Interceptor.class), false)); + if(InterceptorRegistry.isInterceptorHolderEnable()) { + final String className = ASMInterceptorHolder.getInterceptorHolderClassName(interceptorId); + instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, JavaAssistUtils.javaNameToJvmName(className), "get", "()" + Type.getDescriptor(Interceptor.class), false)); + } else { + push(instructions, interceptorId); + instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(InterceptorRegistry.class), "getInterceptor", "(I)" + Type.getDescriptor(Interceptor.class), false)); + } storeVar(instructions, this.interceptorVarIndex); this.resultVarIndex = addInterceptorLocalVariable("_$PINPOINT$_result", "Ljava/lang/Object;"); loadNull(instructions); diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/DefaultEngineComponent.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/DefaultEngineComponent.java index 4ea30bf927cc..6b09bcabdfb6 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/DefaultEngineComponent.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/DefaultEngineComponent.java @@ -66,10 +66,14 @@ public ObjectBinderFactory getObjectBinderFactory() { return objectBinderFactory; } - @Override public int addInterceptor(Interceptor interceptor) { - return interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(interceptor); + return interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(interceptor); + } + + @Override + public int addInterceptor() { + return interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(); } @Override @@ -77,6 +81,5 @@ public int cacheApi(MethodDescriptor methodDescriptor) { ApiMetaDataService apiMetaDataService = this.apiMetaDataServiceProvider.get(); return apiMetaDataService.cacheApi(methodDescriptor); } - } diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/EngineComponent.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/EngineComponent.java index a857c436af78..88f1c2e20554 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/EngineComponent.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/EngineComponent.java @@ -34,5 +34,7 @@ public interface EngineComponent { int addInterceptor(Interceptor interceptor); + int addInterceptor(); + int cacheApi(MethodDescriptor methodDescriptor); } diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classloading/InterceptorDefineClassHelper.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classloading/InterceptorDefineClassHelper.java new file mode 100644 index 000000000000..35f92d9a581c --- /dev/null +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classloading/InterceptorDefineClassHelper.java @@ -0,0 +1,24 @@ +/* + * Copyright 2024 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.instrument.classloading; + +public class InterceptorDefineClassHelper { + + public static Class defineClass(ClassLoader classLoader, String name, byte[] bytes) { + return DefineClassFactory.getDefineClass().defineClass(classLoader, name, bytes); + } +} diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/config/DefaultInstrumentConfig.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/config/DefaultInstrumentConfig.java index 2b7556235fd3..09e6f546567a 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/config/DefaultInstrumentConfig.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/config/DefaultInstrumentConfig.java @@ -38,6 +38,9 @@ public class DefaultInstrumentConfig implements InstrumentConfig { @Value("${profiler.interceptorregistry.size}") private int interceptorRegistrySize = 1024 * 8; + @Value("${profiler.interceptor.holder.enable}") + private boolean interceptorHolderEnable = true; + private List allowJdkClassNames = Collections.emptyList(); @Value("${profiler.pinpoint.base-package}") @@ -66,6 +69,11 @@ public int getInterceptorRegistrySize() { return interceptorRegistrySize; } + @Override + public boolean getInterceptorHolderEnable() { + return interceptorHolderEnable; + } + @Override public List getAllowJdkClassName() { return allowJdkClassNames; @@ -183,10 +191,13 @@ public String toString() { "profileInstrumentEngine='" + profileInstrumentEngine + '\'' + ", instrumentMatcherEnable=" + instrumentMatcherEnable + ", interceptorRegistrySize=" + interceptorRegistrySize + + ", interceptorHolderEnable=" + interceptorHolderEnable + ", allowJdkClassNames=" + allowJdkClassNames + ", pinpointBasePackage='" + pinpointBasePackage + '\'' + ", pinpointExcludePackage='" + pinpointExcludePackage + '\'' + ", callStackMaxDepth=" + callStackMaxDepth + + ", callStackMaxSequence=" + callStackMaxSequence + + ", callStackOverflowLogRation=" + callStackOverflowLogRation + ", profilableClassFilter=" + profilableClassFilter + ", applicationServerType='" + applicationServerType + '\'' + ", propagateInterceptorException=" + propagateInterceptorException + diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/config/InstrumentConfig.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/config/InstrumentConfig.java index 3bde8ac1c0d8..a8d58dfa7ce7 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/config/InstrumentConfig.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/config/InstrumentConfig.java @@ -24,6 +24,7 @@ public interface InstrumentConfig { String INSTRUMENT_ENGINE_ASM = "ASM"; int getInterceptorRegistrySize(); + boolean getInterceptorHolderEnable(); List getAllowJdkClassName(); diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorHolder.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorHolder.java new file mode 100644 index 000000000000..2c00b6e3a807 --- /dev/null +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorHolder.java @@ -0,0 +1,39 @@ +/* + * Copyright 2023 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.instrument.interceptor; + +import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; + +import java.util.function.Supplier; + +// Only bytecode +public class InterceptorHolder { + + private static Supplier supplier; + + public static Interceptor get() { + return LazyLoading.INTERCEPTOR; + } + + public static void set(Supplier interceptorSupplier) { + supplier = interceptorSupplier; + } + + static class LazyLoading { + static Interceptor INTERCEPTOR = supplier.get(); + } +} diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorLazyLoadingSupplier.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorLazyLoadingSupplier.java new file mode 100644 index 000000000000..897c381e93d6 --- /dev/null +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorLazyLoadingSupplier.java @@ -0,0 +1,46 @@ +/* + * Copyright 2024 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.instrument.interceptor; + +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; +import com.navercorp.pinpoint.profiler.instrument.ScopeInfo; +import com.navercorp.pinpoint.profiler.interceptor.factory.InterceptorFactory; + +import java.util.function.Supplier; + +public class InterceptorLazyLoadingSupplier implements Supplier { + private final InterceptorFactory factory; + private final Class interceptorClass; + private final Object[] providedArguments; + private final ScopeInfo scopeInfo; + private final MethodDescriptor methodDescriptor; + + public InterceptorLazyLoadingSupplier(InterceptorFactory factory, Class interceptorClass, Object[] providedArguments, ScopeInfo scopeInfo, MethodDescriptor methodDescriptor) { + this.factory = factory; + this.interceptorClass = interceptorClass; + this.providedArguments = providedArguments; + this.scopeInfo = scopeInfo; + this.methodDescriptor = methodDescriptor; + } + + @Override + public Interceptor get() { + Interceptor interceptor = factory.newInterceptor(interceptorClass, providedArguments, scopeInfo, methodDescriptor); + return interceptor; + } +} diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorSupplier.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorSupplier.java new file mode 100644 index 000000000000..72f2e67f3bd3 --- /dev/null +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorSupplier.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024 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.instrument.interceptor; + +import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; + +import java.util.function.Supplier; + +public class InterceptorSupplier implements Supplier { + private final Interceptor interceptor; + + public InterceptorSupplier(Interceptor interceptor) { + this.interceptor = interceptor; + } + + @Override + public Interceptor get() { + return interceptor; + } +} diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/factory/AnnotatedInterceptorFactory.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/factory/AnnotatedInterceptorFactory.java index aed3fa718f86..dcea63f57bd8 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/factory/AnnotatedInterceptorFactory.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/factory/AnnotatedInterceptorFactory.java @@ -17,10 +17,9 @@ package com.navercorp.pinpoint.profiler.interceptor.factory; import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; import com.navercorp.pinpoint.bootstrap.context.TraceContext; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentContext; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod; import com.navercorp.pinpoint.bootstrap.interceptor.ApiIdAwareAroundInterceptor; import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor; import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor0; @@ -106,14 +105,12 @@ public AnnotatedInterceptorFactory(ProfilerConfig profilerConfig, } @Override - public Interceptor newInterceptor(Class interceptorClass, Object[] providedArguments, ScopeInfo scopeInfo, InstrumentClass target, InstrumentMethod targetMethod) { + public Interceptor newInterceptor(Class interceptorClass, Object[] providedArguments, ScopeInfo scopeInfo, MethodDescriptor methodDescriptor) { Objects.requireNonNull(interceptorClass, "interceptorClass"); Objects.requireNonNull(scopeInfo, "scopeInfo"); final InterceptorScope interceptorScope = scopeInfo.getInterceptorScope(); - InterceptorArgumentProvider interceptorArgumentProvider = new InterceptorArgumentProvider(dataSourceMonitorRegistry, - customMetricRegistry, apiMetaDataService, requestRecorderFactory, interceptorScope, target, targetMethod); - + InterceptorArgumentProvider interceptorArgumentProvider = new InterceptorArgumentProvider(dataSourceMonitorRegistry, customMetricRegistry, apiMetaDataService, requestRecorderFactory, interceptorScope, methodDescriptor); AutoBindingObjectFactory factory = new AutoBindingObjectFactory(profilerConfig, traceContext, pluginContext, interceptorClass.getClassLoader()); Interceptor interceptor = (Interceptor) factory.createInstance(interceptorClass, providedArguments, interceptorArgumentProvider); diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/factory/InterceptorFactory.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/factory/InterceptorFactory.java index e7dafd7884e6..43e749596c4c 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/factory/InterceptorFactory.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/factory/InterceptorFactory.java @@ -16,11 +16,10 @@ package com.navercorp.pinpoint.profiler.interceptor.factory; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod; +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; import com.navercorp.pinpoint.profiler.instrument.ScopeInfo; public interface InterceptorFactory { - Interceptor newInterceptor(Class interceptorClass, Object[] providedArguments, ScopeInfo scopeInfo, InstrumentClass target, InstrumentMethod targetMethod); + Interceptor newInterceptor(Class interceptorClass, Object[] providedArguments, ScopeInfo scopeInfo, MethodDescriptor methodDescriptor); } diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/registry/DefaultInterceptorRegistryBinder.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/registry/DefaultInterceptorRegistryBinder.java index 7f050e062278..98c99b13bff5 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/registry/DefaultInterceptorRegistryBinder.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/registry/DefaultInterceptorRegistryBinder.java @@ -38,11 +38,12 @@ public class DefaultInterceptorRegistryBinder implements InterceptorRegistryBind private final InterceptorRegistryAdaptor interceptorRegistryAdaptor; public DefaultInterceptorRegistryBinder() { - this(DEFAULT_MAX); + this(DEFAULT_MAX, true); } - public DefaultInterceptorRegistryBinder(int maxRegistrySize) { + public DefaultInterceptorRegistryBinder(int maxRegistrySize, boolean interceptorHolderEnable) { this.interceptorRegistryAdaptor = new DefaultInterceptorRegistryAdaptor(maxRegistrySize); + InterceptorRegistry.setInterceptorHolderEnable(interceptorHolderEnable); } @Override diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/objectfactory/InterceptorArgumentProvider.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/objectfactory/InterceptorArgumentProvider.java index e77c1df1d6e4..086998ab7ae6 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/objectfactory/InterceptorArgumentProvider.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/objectfactory/InterceptorArgumentProvider.java @@ -15,8 +15,6 @@ package com.navercorp.pinpoint.profiler.objectfactory; import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod; import com.navercorp.pinpoint.bootstrap.interceptor.annotation.Name; import com.navercorp.pinpoint.bootstrap.interceptor.annotation.NoCache; import com.navercorp.pinpoint.bootstrap.interceptor.scope.InterceptorScope; @@ -38,46 +36,38 @@ public class InterceptorArgumentProvider implements ArgumentProvider { private final CustomMetricRegistry customMetricRegistry; private final ApiMetaDataService apiMetaDataService; private final InterceptorScope interceptorScope; - private final InstrumentClass targetClass; - private final InstrumentMethod targetMethod; + private final MethodDescriptor methodDescriptor; private final RequestRecorderFactory requestRecorderFactory; public InterceptorArgumentProvider(DataSourceMonitorRegistry dataSourceMonitorRegistry, CustomMetricRegistry customMetricRegistry, ApiMetaDataService apiMetaDataService, - RequestRecorderFactory requestRecorderFactory, - InstrumentClass targetClass) { - this(dataSourceMonitorRegistry, customMetricRegistry, apiMetaDataService, requestRecorderFactory, null, targetClass, null); + RequestRecorderFactory requestRecorderFactory) { + this(dataSourceMonitorRegistry, customMetricRegistry, apiMetaDataService, requestRecorderFactory, null, null); } public InterceptorArgumentProvider(DataSourceMonitorRegistry dataSourceMonitorRegistry, CustomMetricRegistry customMetricRegistry, ApiMetaDataService apiMetaDataService, RequestRecorderFactory requestRecorderFactory, - InterceptorScope interceptorScope, InstrumentClass targetClass, - InstrumentMethod targetMethod) { + InterceptorScope interceptorScope, + MethodDescriptor methodDescriptor) { this.dataSourceMonitorRegistry = Objects.requireNonNull(dataSourceMonitorRegistry, "dataSourceMonitorRegistry"); this.customMetricRegistry = Objects.requireNonNull(customMetricRegistry, "customMetricRegistry"); this.apiMetaDataService = Objects.requireNonNull(apiMetaDataService, "apiMetaDataService"); this.requestRecorderFactory = requestRecorderFactory; this.interceptorScope = interceptorScope; - this.targetClass = targetClass; - this.targetMethod = targetMethod; - + this.methodDescriptor = methodDescriptor; } @Override public Option get(int index, Class type, Annotation[] annotations) { - if (type == InstrumentClass.class) { - return Option.withValue(targetClass); - } else if (type == MethodDescriptor.class) { - MethodDescriptor descriptor = targetMethod.getDescriptor(); - cacheApiIfAnnotationNotPresent(annotations, descriptor); - - return Option.withValue(descriptor); - } else if (type == InstrumentMethod.class) { - return Option.withValue(targetMethod); + if (type == MethodDescriptor.class) { + if (methodDescriptor != null) { + cacheApiIfAnnotationNotPresent(annotations, methodDescriptor); + } + return Option.withValue(methodDescriptor); } else if (type == InterceptorScope.class) { Name annotation = TypeUtils.findAnnotation(annotations, Name.class); diff --git a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/objectfactory/ObjectBinderFactory.java b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/objectfactory/ObjectBinderFactory.java index e0452d64b8cc..217fcff21aec 100644 --- a/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/objectfactory/ObjectBinderFactory.java +++ b/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/objectfactory/ObjectBinderFactory.java @@ -19,7 +19,6 @@ import com.google.inject.Provider; import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; import com.navercorp.pinpoint.bootstrap.context.TraceContext; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentContext; import com.navercorp.pinpoint.bootstrap.plugin.RequestRecorderFactory; import com.navercorp.pinpoint.bootstrap.plugin.monitor.DataSourceMonitorRegistry; @@ -76,9 +75,9 @@ public AutoBindingObjectFactory newAutoBindingObjectFactory(InstrumentContext pl } - public InterceptorArgumentProvider newInterceptorArgumentProvider(InstrumentClass instrumentClass) { + public InterceptorArgumentProvider newInterceptorArgumentProvider() { ApiMetaDataService apiMetaDataService = this.apiMetaDataServiceProvider.get(); - return new InterceptorArgumentProvider(dataSourceMonitorRegistry, customMetricRegistry, apiMetaDataService, requestRecorderFactory, instrumentClass); + return new InterceptorArgumentProvider(dataSourceMonitorRegistry, customMetricRegistry, apiMetaDataService, requestRecorderFactory); } public AnnotatedInterceptorFactory newAnnotatedInterceptorFactory(InstrumentContext pluginContext) { diff --git a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMInterceptorHolderTest.java b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMInterceptorHolderTest.java new file mode 100644 index 000000000000..a5b92f07a7e0 --- /dev/null +++ b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMInterceptorHolderTest.java @@ -0,0 +1,214 @@ +/* + * Copyright 2023 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.instrument; + +import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorHolder; +import com.navercorp.pinpoint.profiler.util.JavaAssistUtils; +import org.junit.jupiter.api.Test; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.tree.ClassNode; + +public class ASMInterceptorHolderTest { + + @Test + public void mainClass() throws Exception { + ClassLoader classLoader = InterceptorHolder.class.getClassLoader(); + final String classFileName = JavaAssistUtils.javaNameToJvmName(InterceptorHolder.class.getName()) + ".class"; + + final ClassReader classReader = new ClassReader(classLoader.getResourceAsStream(classFileName)); + ClassNode classNode = new ClassNode(); + classReader.accept(classNode, 0); + + final ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + RenameClassAdapter renameClassAdapter = new RenameClassAdapter(ASMVersion.VERSION, classWriter, "foo.bar.Interceptor111"); + classNode.accept(renameClassAdapter); + byte[] bytes = classWriter.toByteArray(); + + ASMBytecodeDisassembler bytecodeDisassembler = new ASMBytecodeDisassembler(); + String result = bytecodeDisassembler.dumpBytecode(bytes); + System.out.println("## Main Class"); + System.out.println(result); + } + + @Test + public void innerClass() throws Exception { + ClassLoader classLoader = InterceptorHolder.class.getClassLoader(); + final String classFileName = JavaAssistUtils.javaNameToJvmName(InterceptorHolder.class.getName()) + "$LazyLoading.class"; + + final ClassReader classReader = new ClassReader(classLoader.getResourceAsStream(classFileName)); + ClassNode classNode = new ClassNode(); + classReader.accept(classNode, 0); + + final ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + RenameInnerClassAdapter renameClassAdapter = new RenameInnerClassAdapter(ASMVersion.VERSION, classWriter, "foo.bar.Interceptor111"); + classNode.accept(renameClassAdapter); + byte[] bytes = classWriter.toByteArray(); + + ASMBytecodeDisassembler bytecodeDisassembler = new ASMBytecodeDisassembler(); + String result = bytecodeDisassembler.dumpBytecode(bytes); + System.out.println("## Inner Class"); + System.out.println(result); + } + + + class RenameClassAdapter extends ClassVisitor { + private final String newInternalName; + + public RenameClassAdapter(int api, ClassVisitor classVisitor, String name) { + super(api, classVisitor); + this.newInternalName = JavaAssistUtils.javaNameToJvmName(name); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, this.newInternalName, signature, superName, interfaces); + } + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + super.visitInnerClass(newInternalName + "$" + innerName, newInternalName, innerName, access); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + if (name.equals("")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { + // LOCALVARIABLE this Lcom/navercorp/pinpoint/profiler/instrument/mock/InterceptorHolder; L0 L1 0 + if (name.equals("this")) { + final String newDescriptor = "L" + newInternalName + ";"; + super.visitLocalVariable(name, newDescriptor, signature, start, end, index); + } else { + super.visitLocalVariable(name, descriptor, signature, start, end, index); + } + } + }; + } else if (name.equals("get")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + // GETSTATIC com/navercorp/pinpoint/profiler/instrument/mock/InterceptorHolder.holder : Lcom/navercorp/pinpoint/bootstrap/interceptor/Interceptor; + final int innerNameStartPosition = owner.indexOf('$'); + if (innerNameStartPosition != -1) { + final String innerName = owner.substring(innerNameStartPosition); + super.visitFieldInsn(opcode, newInternalName + innerName, name, descriptor); + } else { + super.visitFieldInsn(opcode, newInternalName, name, descriptor); + } + } + }; + } else if (name.equals("set")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + // PUTSTATIC com/navercorp/pinpoint/profiler/instrument/mock/InterceptorBinder.binder : Lcom/navercorp/pinpoint/bootstrap/interceptor/Interceptor; + super.visitFieldInsn(opcode, newInternalName, name, descriptor); + } + }; + } else if (name.equals("access$000")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + // GETSTATIC com/navercorp/pinpoint/profiler/instrument/mock/InterceptorBinder.factory : Lcom/navercorp/pinpoint/profiler/instrument/mock/InterceptorLazyFactory; + super.visitFieldInsn(opcode, newInternalName, name, descriptor); + } + }; + } + + return super.visitMethod(access, name, descriptor, signature, exceptions); + } + } + + class RenameInnerClassAdapter extends ClassVisitor { + private final String newInternalName; + + public RenameInnerClassAdapter(int api, ClassVisitor classVisitor, String name) { + super(api, classVisitor); + this.newInternalName = JavaAssistUtils.javaNameToJvmName(name); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + final int innerNameStartPosition = name.indexOf('$'); + if (innerNameStartPosition != -1) { + final String innerName = name.substring(innerNameStartPosition); + super.visit(version, access, this.newInternalName + innerName, signature, superName, interfaces); + } else { + super.visit(version, access, this.newInternalName, signature, superName, interfaces); + } + } + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + super.visitInnerClass(newInternalName + "$" + innerName, newInternalName, innerName, access); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + if (name.equals("")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { + // LOCALVARIABLE this Lcom/navercorp/pinpoint/profiler/instrument/mock/InterceptorHolder; L0 L1 0 + if (name.equals("this")) { + final int innerNameStartPosition = descriptor.indexOf('$'); + if (innerNameStartPosition != -1) { + final String innerName = descriptor.substring(innerNameStartPosition); + final String newDescriptor = "L" + newInternalName + innerName; + super.visitLocalVariable(name, newDescriptor, signature, start, end, index); + } else { + super.visitLocalVariable(name, descriptor, signature, start, end, index); + } + } else { + super.visitLocalVariable(name, descriptor, signature, start, end, index); + } + } + }; + } else if (name.equals("")) { + return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { + if (name.equals("access$000")) { + super.visitMethodInsn(opcode, newInternalName, name, descriptor, isInterface); + } else { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + } + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + // GETSTATIC com/navercorp/pinpoint/profiler/instrument/mock/InterceptorHolder.holder : Lcom/navercorp/pinpoint/bootstrap/interceptor/Interceptor; + final int innerNameStartPosition = owner.indexOf('$'); + if (innerNameStartPosition != -1) { + final String innerName = owner.substring(innerNameStartPosition); + super.visitFieldInsn(opcode, newInternalName + innerName, name, descriptor); + } else { + super.visitFieldInsn(opcode, newInternalName, name, descriptor); + } + } + }; + } + + return super.visitMethod(access, name, descriptor, signature, exceptions); + } + } +} diff --git a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodNodeAdapterAddInterceptorTest.java b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodNodeAdapterAddInterceptorTest.java index 3fe2204dcec2..881e111d6cf6 100644 --- a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodNodeAdapterAddInterceptorTest.java +++ b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodNodeAdapterAddInterceptorTest.java @@ -15,24 +15,18 @@ */ package com.navercorp.pinpoint.profiler.instrument; +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor; import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandler; +import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; +import com.navercorp.pinpoint.bootstrap.interceptor.registry.InterceptorRegistry; import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorDefinition; import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorDefinitionFactory; -import com.navercorp.pinpoint.profiler.instrument.mock.ApiIdAwareInterceptor; -import com.navercorp.pinpoint.profiler.instrument.mock.ArgsArrayInterceptor; -import com.navercorp.pinpoint.profiler.instrument.mock.BaseEnum; -import com.navercorp.pinpoint.profiler.instrument.mock.BasicInterceptor; -import com.navercorp.pinpoint.profiler.instrument.mock.ExceptionInterceptor; -import com.navercorp.pinpoint.profiler.instrument.mock.StaticInterceptor; +import com.navercorp.pinpoint.profiler.instrument.mock.*; import com.navercorp.pinpoint.profiler.interceptor.factory.ExceptionHandlerFactory; import com.navercorp.pinpoint.profiler.interceptor.registry.InterceptorRegistryBinder; import com.navercorp.pinpoint.profiler.util.TestInterceptorRegistryBinder; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; @@ -43,23 +37,22 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.*; public class ASMMethodNodeAdapterAddInterceptorTest { private final static InterceptorRegistryBinder interceptorRegistryBinder = new TestInterceptorRegistryBinder(); private ASMClassNodeLoader.TestClassLoader classLoader; + private AtomicInteger interceptorIdCounter = new AtomicInteger(); private ExceptionHandlerFactory exceptionHandlerFactory = new ExceptionHandlerFactory(false); @BeforeAll public static void beforeClass() { interceptorRegistryBinder.bind(); + InterceptorRegistry.setInterceptorHolderEnable(true); } @AfterAll @@ -74,26 +67,22 @@ public void before() { @Test public void addArgsArrayInterceptor() throws Exception { - int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new ArgsArrayInterceptor()); - addInterceptor(interceptorId, ArgsArrayInterceptor.class); + addInterceptor(new ArgsArrayInterceptor()); } @Test public void addStaticInterceptor() throws Exception { - int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new StaticInterceptor()); - addInterceptor(interceptorId, StaticInterceptor.class); + addInterceptor(new StaticInterceptor()); } @Test public void addApiIdAwareInterceptor() throws Exception { - int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new ApiIdAwareInterceptor()); - addInterceptor(interceptorId, ApiIdAwareInterceptor.class); + addInterceptor(new ApiIdAwareInterceptor()); } @Test public void addBasicInterceptor() throws Exception { - int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new BasicInterceptor()); - addInterceptor(interceptorId, BasicInterceptor.class); + addInterceptor(new BasicInterceptor()); } @Disabled @@ -101,35 +90,34 @@ public void addBasicInterceptor() throws Exception { public void addExceptionInterceptor() throws Exception { ExceptionHandler exceptionHandler = exceptionHandlerFactory.getExceptionHandler(); ExceptionHandleAroundInterceptor interceptor = new ExceptionHandleAroundInterceptor(new ExceptionInterceptor(), exceptionHandler); - int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(interceptor); - addInterceptor(interceptorId, ExceptionHandleAroundInterceptor.class); + addInterceptor(interceptor); } - private void addInterceptor(int interceptorId, Class interceptorClass) throws Exception { + private void addInterceptor(Interceptor interceptor) throws Exception { // method - checkMethod(interceptorId, interceptorClass); + checkMethod(interceptor); // constructor - checkConstructor(interceptorId, interceptorClass); + checkConstructor(interceptor); // arguments - checkArguments(interceptorId, interceptorClass); + checkArguments(interceptor); // return - checkReturn(interceptorId, interceptorClass); + checkReturn(interceptor); // exception - checkMethodException(interceptorId, interceptorClass); - checkConstructorException(interceptorId, interceptorClass); + checkMethodException(interceptor); + checkConstructorException(interceptor); // extend - checkExtends(interceptorId, interceptorClass); + checkExtends(interceptor); } - private void checkMethod(int interceptorId, Class interceptorClass) throws Exception { + private void checkMethod(Interceptor interceptor) throws Exception { // method - Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.MethodClass", interceptorClass); - + Class clazz = addInterceptor0("com.navercorp.pinpoint.profiler.instrument.mock.MethodClass", interceptor); + Class interceptorClass = interceptor.getClass(); Class[] parameterTypes = new Class[0]; Object[] args = new Object[0]; invokeMethod(clazz, "publicMethod", interceptorClass, parameterTypes, args, null, false); @@ -141,9 +129,9 @@ private void checkMethod(int interceptorId, Class interceptorClass) throws Ex invokeMethod(clazz, "publicStaticFinalSynchronizedMethod", interceptorClass, parameterTypes, args, null, false); } - private void checkConstructor(int interceptorId, Class interceptorClass) throws Exception { - Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ConstructorClass", interceptorClass); - + private void checkConstructor(Interceptor interceptor) throws Exception { + Class clazz = addInterceptor0("com.navercorp.pinpoint.profiler.instrument.mock.ConstructorClass", interceptor); + Class interceptorClass = interceptor.getClass(); invokeMethod(clazz, "", interceptorClass, new Class[0], new Object[0], null, false); invokeMethod(clazz, "", interceptorClass, new Class[]{byte.class}, new Object[]{Byte.parseByte("0")}, null, false); invokeMethod(clazz, "", interceptorClass, new Class[]{short.class}, new Object[]{Short.parseShort("0")}, null, false); @@ -206,8 +194,9 @@ private void checkConstructor(int interceptorId, Class interceptorClass) thro invokeMethod(clazz, "", interceptorClass, new Class[]{String.class, int.class, byte.class, Object.class, Enum.class, char.class, float.class, long.class}, new Object[]{"foo", 1, Byte.parseByte("0"), new Object(), BaseEnum.AGENT, 'a', 1.1f, 1l}, null, false); } - private void checkArguments(int interceptorId, Class interceptorClass) throws Exception { - Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ArgsClass", interceptorClass); + private void checkArguments(Interceptor interceptor) throws Exception { + Class clazz = addInterceptor0("com.navercorp.pinpoint.profiler.instrument.mock.ArgsClass", interceptor); + Class interceptorClass = interceptor.getClass(); invokeMethod(clazz, "arg", interceptorClass, new Class[0], new Object[0], null, false); invokeMethod(clazz, "argByteType", interceptorClass, new Class[]{byte.class}, new Object[]{Byte.parseByte("0")}, null, false); @@ -243,8 +232,9 @@ private void checkArguments(int interceptorId, Class interceptorClass) throws invokeMethod(clazz, "argInterface", interceptorClass, new Class[]{Map.class, Map.class, Map.class}, new Object[]{new HashMap(), new HashMap(), new HashMap()}, null, false); } - private void checkReturn(int interceptorId, Class interceptorClass) throws Exception { - Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ReturnClass", interceptorClass); + private void checkReturn(Interceptor interceptor) throws Exception { + Class clazz = addInterceptor0("com.navercorp.pinpoint.profiler.instrument.mock.ReturnClass", interceptor); + Class interceptorClass = interceptor.getClass(); invokeMethod(clazz, "voidType", interceptorClass, new Class[0], new Object[0], null, false); invokeMethod(clazz, "returnByte", interceptorClass, new Class[0], new Object[0], Byte.parseByte("0"), false); @@ -261,8 +251,9 @@ private void checkReturn(int interceptorId, Class interceptorClass) throws Ex invokeMethod(clazz, "returnEnum", interceptorClass, new Class[0], new Object[0], BaseEnum.AGENT, false); } - private void checkMethodException(int interceptorId, Class interceptorClass) throws Exception { - Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ExceptionClass", interceptorClass); + private void checkMethodException(Interceptor interceptor) throws Exception { + Class clazz = addInterceptor0("com.navercorp.pinpoint.profiler.instrument.mock.ExceptionClass", interceptor); + Class interceptorClass = interceptor.getClass(); invokeMethod(clazz, "throwable", interceptorClass, new Class[]{}, new Object[]{}, null, true); invokeMethod(clazz, "exception", interceptorClass, new Class[]{}, new Object[]{}, null, true); @@ -272,17 +263,20 @@ private void checkMethodException(int interceptorId, Class interceptorClass) invokeMethod(clazz, "condition", interceptorClass, new Class[]{}, new Object[]{}, null, true); } - private void checkConstructorException(int interceptorId, Class interceptorClass) throws Exception { - Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ConstructorExceptionClass", interceptorClass); + private void checkConstructorException(Interceptor interceptor) throws Exception { + Class clazz = addInterceptor0("com.navercorp.pinpoint.profiler.instrument.mock.ConstructorExceptionClass", interceptor); + Class interceptorClass = interceptor.getClass(); invokeMethod(clazz, "", interceptorClass, new Class[]{String.class, int.class}, new Object[]{"foo", 0}, null, true); invokeMethod(clazz, "", interceptorClass, new Class[]{Boolean.class}, new Object[]{Boolean.TRUE}, null, true); invokeMethod(clazz, "", interceptorClass, new Class[]{Boolean.class}, new Object[]{Boolean.FALSE}, null, false); } - private void checkExtends(int interceptorId, Class interceptorClass) throws Exception { - addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ConstructorParentClass", interceptorClass); - Class clazz = addInterceptor(interceptorId, "com.navercorp.pinpoint.profiler.instrument.mock.ConstructorChildClass", interceptorClass); + private void checkExtends(Interceptor interceptor) throws Exception { + addInterceptor0("com.navercorp.pinpoint.profiler.instrument.mock.ConstructorParentClass", interceptor); + Class interceptorClass = interceptor.getClass(); + + Class clazz = addInterceptor0("com.navercorp.pinpoint.profiler.instrument.mock.ConstructorChildClass", interceptor); invokeMethod(clazz, "", interceptorClass, new Class[]{}, new Object[]{}, null, false); invokeMethod(clazz, "", interceptorClass, new Class[]{String.class}, new Object[]{"foo"}, null, false); invokeMethod(clazz, "", interceptorClass, new Class[]{String.class, int.class}, new Object[]{"foo", 1}, null, false); @@ -480,8 +474,8 @@ private void invokeMethod(final Class clazz, final String methodName, final C } } - private Class addInterceptor(final int interceptorId, final String targetClassName, final Class interceptorClass) { - final InterceptorDefinition interceptorDefinition = new InterceptorDefinitionFactory().createInterceptorDefinition(interceptorClass); + private Class addInterceptor0(final String targetClassName, Interceptor interceptor) { + final InterceptorDefinition interceptorDefinition = new InterceptorDefinitionFactory().createInterceptorDefinition(interceptor.getClass()); try { classLoader.setTrace(false); classLoader.setVerify(false); @@ -499,6 +493,12 @@ public void handle(ClassNode classNode) { if (methodNodeAdapter.isAbstract() || methodNodeAdapter.isNative()) { continue; } + int interceptorId = interceptorIdCounter.incrementAndGet(); + try { + ASMInterceptorHolder.create(interceptorId, classLoader, interceptor); + } catch (InstrumentException e) { + throw new RuntimeException(e); + } methodNodeAdapter.addBeforeInterceptor(interceptorId, interceptorDefinition, 99); methodNodeAdapter.addAfterInterceptor(interceptorId, interceptorDefinition, 99); } diff --git a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodNodeTest.java b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodNodeTest.java index 4de143fc66a3..c4da5e50c1e0 100644 --- a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodNodeTest.java +++ b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/ASMMethodNodeTest.java @@ -17,11 +17,12 @@ import com.navercorp.pinpoint.bootstrap.instrument.InstrumentContext; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; +import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorDefinition; import com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorDefinitionFactory; import com.navercorp.pinpoint.profiler.instrument.mock.ArgsArrayInterceptor; -import com.navercorp.pinpoint.profiler.interceptor.registry.DefaultInterceptorRegistryBinder; -import com.navercorp.pinpoint.profiler.interceptor.registry.InterceptorRegistryBinder; +import com.navercorp.pinpoint.profiler.interceptor.factory.AnnotatedInterceptorFactory; +import com.navercorp.pinpoint.profiler.objectfactory.ObjectBinderFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.invocation.InvocationOnMock; @@ -31,6 +32,7 @@ import java.lang.reflect.Method; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -44,7 +46,6 @@ */ public class ASMMethodNodeTest { - private final InterceptorRegistryBinder interceptorRegistryBinder = new DefaultInterceptorRegistryBinder(); private final InterceptorDefinitionFactory interceptorDefinitionFactory = new InterceptorDefinitionFactory(); private final InstrumentContext pluginContext = mock(InstrumentContext.class); @@ -88,11 +89,15 @@ public void getter() throws Exception { } @Test - public void addInterceptor() throws Exception { - final int interceptorId = interceptorRegistryBinder.getInterceptorRegistryAdaptor().addInterceptor(new ArgsArrayInterceptor()); + public void addArgsArrayInterceptor() throws Exception { + addInterceptor(new ArgsArrayInterceptor(), ArgsArrayInterceptor.class); + } + + void addInterceptor(Interceptor interceptor, Class interceptorClass) throws Exception { final String targetClassName = "com.navercorp.pinpoint.profiler.instrument.mock.NormalClass"; final ASMClass declaringClass = mock(ASMClass.class); when(declaringClass.getName()).thenReturn(targetClassName); + when(declaringClass.getClassLoader()).thenReturn(Thread.currentThread().getContextClassLoader()); final EngineComponent engineComponent = mock(EngineComponent.class); when(engineComponent.createInterceptorDefinition(any(Class.class))).thenAnswer(new Answer() { @Override @@ -102,7 +107,39 @@ public InterceptorDefinition answer(InvocationOnMock invocation) throws Throwabl return interceptorDefinitionFactory.createInterceptorDefinition(clazz); } }); - + final AtomicInteger interceptorRegistryCount = new AtomicInteger(); + when(engineComponent.addInterceptor()).thenAnswer(new Answer() { + @Override + public Integer answer(InvocationOnMock invocation) throws Throwable { + return interceptorRegistryCount.incrementAndGet(); + } + }); + final ObjectBinderFactory objectBinderFactory = mock(ObjectBinderFactory.class); + when(engineComponent.getScopeFactory()).thenAnswer(new Answer() { + @Override + public ScopeFactory answer(InvocationOnMock invocation) throws Throwable { + return new ScopeFactory(); + } + }); + when(engineComponent.getObjectBinderFactory()).thenAnswer(new Answer() { + @Override + public ObjectBinderFactory answer(InvocationOnMock invocation) throws Throwable { + return objectBinderFactory; + } + }); + final AnnotatedInterceptorFactory annotatedInterceptorFactory = mock(AnnotatedInterceptorFactory.class); + when(objectBinderFactory.newAnnotatedInterceptorFactory(any())).thenAnswer(new Answer() { + @Override + public AnnotatedInterceptorFactory answer(InvocationOnMock invocation) throws Throwable { + return annotatedInterceptorFactory; + } + }); + when(annotatedInterceptorFactory.newInterceptor(any(), any(), any(), any())).thenAnswer(new Answer() { + @Override + public Interceptor answer(InvocationOnMock invocation) throws Throwable { + return interceptor; + } + }); ASMClassNodeLoader.TestClassLoader classLoader = ASMClassNodeLoader.getClassLoader(); @@ -117,7 +154,7 @@ public void handle(ClassNode classNode) { for (MethodNode methodNode : methodNodes) { ASMMethod method = new ASMMethod(engineComponent, pluginContext, declaringClass, methodNode); try { - method.addInterceptor(interceptorId); + method.addInterceptor(interceptorClass); } catch (InstrumentException e) { exception[0] = e; e.printStackTrace(); diff --git a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/mock/BaseAnnotationInterceptor.java b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/mock/BaseAnnotationInterceptor.java index d29589085f10..971b28aaae3c 100644 --- a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/mock/BaseAnnotationInterceptor.java +++ b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/instrument/mock/BaseAnnotationInterceptor.java @@ -40,4 +40,4 @@ public void after(Object target, Object[] args, Object result, Throwable throwab this.throwable = true; } } -} +} \ No newline at end of file diff --git a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/AnnotatedInterceptorFactoryTest.java b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/AnnotatedInterceptorFactoryTest.java index f896012934ff..48d789667b75 100644 --- a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/AnnotatedInterceptorFactoryTest.java +++ b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/AnnotatedInterceptorFactoryTest.java @@ -45,7 +45,6 @@ import java.lang.reflect.Method; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; @@ -97,7 +96,7 @@ private ScopeInfo newEmptyScopeInfo() { public void test0() { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor0.class, null, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor0.class, null, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor0.class, interceptor.getClass()); } @@ -109,7 +108,7 @@ public void test1() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor0.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor0.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor0.class, interceptor.getClass()); assertEquals(args[0], getField(interceptor, "field0")); @@ -122,7 +121,7 @@ public void test2() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - factory.newInterceptor(TestInterceptor0.class, args, scopeInfo, instrumentClass, instrumentMethod); + factory.newInterceptor(TestInterceptor0.class, args, scopeInfo, instrumentMethod.getDescriptor()); }); } @@ -132,7 +131,7 @@ public void test3() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor1.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor1.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor1.class, interceptor.getClass()); assertEquals(args[0], getField(interceptor, "field0")); @@ -147,7 +146,7 @@ public void test4() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor1.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor1.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor1.class, interceptor.getClass()); assertEquals(args[3], getField(interceptor, "field0")); @@ -162,7 +161,7 @@ public void test5() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor1.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor1.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor1.class, interceptor.getClass()); assertEquals(args[2], getField(interceptor, "field0")); @@ -177,7 +176,7 @@ public void test6() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor1.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor1.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor1.class, interceptor.getClass()); assertEquals(args[3], getField(interceptor, "field0")); @@ -191,7 +190,7 @@ public void test7() { Assertions.assertThrows(PinpointException.class, () -> { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - factory.newInterceptor(TestInterceptor1.class, null, scopeInfo, instrumentClass, instrumentMethod); + factory.newInterceptor(TestInterceptor1.class, null, scopeInfo, instrumentMethod.getDescriptor()); }); } @@ -200,7 +199,7 @@ public void test8() { Assertions.assertThrows(PinpointException.class, () -> { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - factory.newInterceptor(TestInterceptor1.class, null, scopeInfo, instrumentClass, instrumentMethod); + factory.newInterceptor(TestInterceptor1.class, null, scopeInfo, instrumentMethod.getDescriptor()); }); } @@ -210,7 +209,7 @@ public void test9() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor2.class, interceptor.getClass()); assertEquals(args[0], getField(interceptor, "field0")); @@ -220,8 +219,6 @@ public void test9() throws Exception { assertEquals(args[4], getField(interceptor, "field4")); assertSame(descriptor, getField(interceptor, "descriptor")); - assertSame(instrumentClass, getField(interceptor, "targetClass")); - assertSame(instrumentMethod, getField(interceptor, "targetMethod")); } @Test @@ -230,7 +227,7 @@ public void test10() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor2.class, interceptor.getClass()); assertEquals(args[0], getField(interceptor, "field0")); @@ -240,8 +237,6 @@ public void test10() throws Exception { assertEquals(0L, getField(interceptor, "field4")); assertSame(descriptor, getField(interceptor, "descriptor")); - assertSame(instrumentClass, getField(interceptor, "targetClass")); - assertSame(instrumentMethod, getField(interceptor, "targetMethod")); } @Test @@ -250,7 +245,7 @@ public void test11() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor2.class, interceptor.getClass()); assertEquals(args[0], getField(interceptor, "field0")); @@ -260,15 +255,13 @@ public void test11() throws Exception { assertEquals(0L, getField(interceptor, "field4")); assertSame(descriptor, getField(interceptor, "descriptor")); - assertSame(instrumentClass, getField(interceptor, "targetClass")); - assertSame(instrumentMethod, getField(interceptor, "targetMethod")); } @Test public void test12() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, null, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, null, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor2.class, interceptor.getClass()); assertEquals(null, getField(interceptor, "field0")); @@ -278,8 +271,6 @@ public void test12() throws Exception { assertEquals(0L, getField(interceptor, "field4")); assertSame(descriptor, getField(interceptor, "descriptor")); - assertSame(instrumentClass, getField(interceptor, "targetClass")); - assertSame(instrumentMethod, getField(interceptor, "targetMethod")); } @Test @@ -288,7 +279,7 @@ public void test13() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor2.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor2.class, interceptor.getClass()); assertEquals(args[0], getField(interceptor, "field0")); @@ -298,8 +289,6 @@ public void test13() throws Exception { assertEquals(0L, getField(interceptor, "field4")); assertSame(descriptor, getField(interceptor, "descriptor")); - assertSame(instrumentClass, getField(interceptor, "targetClass")); - assertNull(getField(interceptor, "targetMethod")); } @Test @@ -309,7 +298,7 @@ public void test14() throws Exception { AnnotatedInterceptorFactory factory = newAnnotatedInterceptorFactory(); final ScopeInfo scopeInfo = newEmptyScopeInfo(); - Interceptor interceptor = factory.newInterceptor(TestInterceptor0.class, args, scopeInfo, instrumentClass, instrumentMethod); + Interceptor interceptor = factory.newInterceptor(TestInterceptor0.class, args, scopeInfo, instrumentMethod.getDescriptor()); assertEquals(TestInterceptor0.class, interceptor.getClass()); assertEquals(arg0, getField(interceptor, "field0")); diff --git a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/TestInterceptors.java b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/TestInterceptors.java index 86aa949cd090..d8fc3e614a2a 100644 --- a/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/TestInterceptors.java +++ b/agent-module/profiler/src/test/java/com/navercorp/pinpoint/profiler/plugin/TestInterceptors.java @@ -18,8 +18,6 @@ import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; import com.navercorp.pinpoint.bootstrap.context.TraceContext; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod; import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor; public class TestInterceptors { @@ -110,9 +108,7 @@ public float getField3() { public static class TestInterceptor2 extends AbstractInterceptor { private final TraceContext context; private final MethodDescriptor descriptor; - private final InstrumentClass targetClass; - private final InstrumentMethod targetMethod; - + private final String field0; private final int field1; private final double field2; @@ -120,11 +116,9 @@ public static class TestInterceptor2 extends AbstractInterceptor { private final long field4; - public TestInterceptor2(String field0, TraceContext context, int field1, double field2, MethodDescriptor descriptor, boolean field3, InstrumentClass targetClass, InstrumentMethod targetMethod, long field4) { + public TestInterceptor2(String field0, TraceContext context, int field1, double field2, MethodDescriptor descriptor, boolean field3, long field4) { this.context = context; this.descriptor = descriptor; - this.targetClass = targetClass; - this.targetMethod = targetMethod; this.field0 = field0; this.field1 = field1; this.field2 = field2; @@ -132,11 +126,9 @@ public TestInterceptor2(String field0, TraceContext context, int field1, double this.field4 = field4; } - public TestInterceptor2(String field0, int field1, double field2, TraceContext context, InstrumentClass targetClass, MethodDescriptor descriptor, InstrumentMethod targetMethod) { + public TestInterceptor2(String field0, int field1, double field2, TraceContext context, MethodDescriptor descriptor) { this.context = context; this.descriptor = descriptor; - this.targetClass = targetClass; - this.targetMethod = targetMethod; this.field0 = field0; this.field1 = field1; this.field2 = field2; @@ -144,11 +136,9 @@ public TestInterceptor2(String field0, int field1, double field2, TraceContext c this.field4 = 0; } - public TestInterceptor2(TraceContext context, MethodDescriptor descriptor, InstrumentClass targetClass, InstrumentMethod targetMethod, String field0, int field1) { + public TestInterceptor2(TraceContext context, MethodDescriptor descriptor, String field0, int field1) { this.context = context; this.descriptor = descriptor; - this.targetClass = targetClass; - this.targetMethod = targetMethod; this.field0 = field0; this.field1 = field1; this.field2 = 0; @@ -156,11 +146,9 @@ public TestInterceptor2(TraceContext context, MethodDescriptor descriptor, Instr this.field4 = 0; } - public TestInterceptor2(TraceContext context, InstrumentClass targetClass, MethodDescriptor descriptor, InstrumentMethod targetMethod) { + public TestInterceptor2(TraceContext context, MethodDescriptor descriptor) { this.context = context; this.descriptor = descriptor; - this.targetClass = targetClass; - this.targetMethod = targetMethod; this.field0 = null; this.field1 = 0; this.field2 = 0; @@ -168,11 +156,9 @@ public TestInterceptor2(TraceContext context, InstrumentClass targetClass, Metho this.field4 = 0; } - public TestInterceptor2(MethodDescriptor descriptor, InstrumentClass targetClass, String field0) { + public TestInterceptor2(MethodDescriptor descriptor, String field0) { this.context = null; this.descriptor = descriptor; - this.targetClass = targetClass; - this.targetMethod = null; this.field0 = field0; this.field1 = 0; this.field2 = 0; @@ -188,14 +174,6 @@ public MethodDescriptor getDescriptor() { return descriptor; } - public InstrumentMethod getTargetMethod() { - return targetMethod; - } - - public InstrumentClass getTargetClass() { - return targetClass; - } - public String getField0() { return field0; }