diff --git a/bytekit/README.md b/bytekit/README.md deleted file mode 100644 index 92a56d99e..000000000 --- a/bytekit/README.md +++ /dev/null @@ -1,222 +0,0 @@ - - -## ByteKit - - -## 目标 - -1. 之前的Arthas里的字节码增强,是通过asm来处理的,代码逻辑不好修改,理解困难 -1. 基于ASM提供更高层的字节码处理能力,面向诊断/APM领域,不是通用的字节码库 -1. ByteKit期望能提供一套简洁的API,让开发人员可以比较轻松的完成字节码增强 - -## 对比 - -| 功能 | 函数Enter/Exit注入点 | 绑定数据 | inline | 防止重复增强 | 避免装箱/拆箱开销 |origin调用替换 | `@ExceptionHandler` | -| ---- | ---- |---- | :----: |:----: | :----: |:----: | :----: | -| ByteKit | `@AtEnter`
`@AtExit`
`@AtExceptionExit`
`@AtFieldAccess`
`@AtInvoke`
`@AtInvokeException`
`@AtLine`
`@AtSyncEnter`
`@AtSyncExit`
`@AtThrow`| this/args/return/throw
field
locals
子调用入参/返回值/子调用异常
line number|✓|✓|✓|✓|✓| -| ByteBuddy | `OnMethodEnter`
`@OnMethodExit`
`@OnMethodExit#onThrowable()`| this/args/return/throw
field
locals|✓|✗|✓|✓|✓| -| 传统AOP | `Enter`
`Exit`
`Exception` |this/args/return/throw|✗|✗|✗|✗|✗ - - -## 特性 - -### 1. 丰富的注入点支持 - -* `@AtEnter` 函数入口 -* `@AtExit` 函数退出 -* `@AtExceptionExit` 函数抛出异常 -* `@AtFieldAccess` 访问field -* `@AtInvoke` 在method里的子函数调用 -* `@AtInvokeException` 在method里的子函数调用抛出异常 -* `@AtLine` 在指定行号 -* `@AtSyncEnter` 进入同步块,比如`synchronized`块 -* `@AtSyncExit` 退出同步块 -* `@AtThrow` 代码里显式`throw`异常点 - - -### 2. 动态的Binding - -* `@Binding.This` this对象 -* `@@Binding.Class` Class对象 -* `@Binding.Method` 函数调用的 Method 对象 -* `@Binding.MethodName` 函数的名字 -* `@Binding.MethodDesc` 函数的desc -* `@Binding.Return` 函数调用的返回值 -* `@Binding.Throwable` 函数里抛出的异常 -* `@Binding.Args` 函数调用的入参 -* `@Binding.ArgNames` 函数调用的入参的名字 - - -* `@Binding.LocalVars` 局部变量 -* `@Binding.LocalVarNames` 局部变量的名字 -* `@Binding.Field` field对象属性字段 - - -* `@Binding.InvokeArgs` method里的子函数调用的入参 -* `@Binding.InvokeReturn` method里的子函数调用的返回值 -* `@Binding.InvokeMethodName` method里的子函数调用的名字 -* `@Binding.InvokeMethodOwner` method里的子函数调用的类名 -* `@Binding.InvokeMethodDeclaration` method里的子函数调用的desc - - -* `@Binding.Line` 行号 -* `@Binding.Monitor` 同步块里监控的对象 - - -### 3. 可编程的异常处理 - -* `@ExceptionHandler` 在插入的增强代码,可以用`try/catch`块包围起来 - -### 4. inline支持 - -增强的代码 和 异常处理代码都可以通过 inline技术内联到原来的类里,达到最理想的增强效果。 - -### 5. invokeOrigin 技术 - -通常,我们要增强一个类,就想要办法在函数前后插入一个static的回调函数,但这样子局限太大。那么有没有更灵活的方式呢? - -比如有一个 hello() 函数: - -```java - public String hello(String str) { - return "hello " + str; - } -``` - -我们想对它做增强,那么可以编写下面的代码: - -```java - public String hello(String str) { - System.out.println("before"); - Object value = InstrumentApi.invokeOrigin(); - System.out.println("after, result: " + value); - return object; - } -``` - -增强后的结果是: - -```java - public String hello(String str) { - System.out.println("before"); - Object value = "hello " + str; - System.out.println("after, result: " + value); - return object; - } -``` - -**这种方式可以随意插入代码,非常灵活。** - -## 示例 - -以`ByteKitDemo.java`为例说明,[[查看源文件](src/test/java/com/example/ByteKitDemo.java)]。 - -### 1. 定义注入点和Binding数据 - -* 在下面的 SampleInterceptor 时定义了要注入 `@AtEnter`/`@AtExit`/`@AtExceptionExit`三个地方, -* 用`@Binding`绑定了不同的数据 -* 在`@AtEnter`里配置了 `inline = true`,则说明插入的`SampleInterceptor#atEnter`函数本身会被inline掉 -* 配置了 `suppress = RuntimeException.class` 和 `suppressHandler = PrintExceptionSuppressHandler.class`,说明插入的代码会被 `try/catch` 包围 - -```java - public static class SampleInterceptor { - - @AtEnter(inline = true, suppress = RuntimeException.class, suppressHandler = PrintExceptionSuppressHandler.class) - public static void atEnter(@Binding.This Object object, - @Binding.Class Object clazz, - @Binding.Args Object[] args, - @Binding.MethodName String methodName, - @Binding.MethodDesc String methodDesc) { - System.out.println("atEnter, args[0]: " + args[0]); - } - - @AtExit(inline = true) - public static void atExit(@Binding.Return Object returnObject) { - System.out.println("atExit, returnObject: " + returnObject); - } - - @AtExceptionExit(inline = true, onException = RuntimeException.class) - public static void atExceptionExit(@Binding.Throwable RuntimeException ex, - @Binding.Field(name = "exceptionCount") int exceptionCount) { - System.out.println("atExceptionExit, ex: " + ex.getMessage() + ", field exceptionCount: " + exceptionCount); - } - } -``` - -### 2. @ExceptionHandler - -在上面的 `@AtEnter`配置里,生成的代码会被 try/catch 包围,那么具体的内容是在`PrintExceptionSuppressHandler`里 - -```java - public static class PrintExceptionSuppressHandler { - - @ExceptionHandler(inline = true) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.out.println("exception handler: " + clazz); - e.printStackTrace(); - } - } -``` - -### 3. 查看反编译结果 - -原始的Sample类是: - -```java - public static class Sample { - private int exceptionCount = 0; - - public String hello(String str, boolean exception) { - if (exception) { - exceptionCount++; - throw new RuntimeException("test exception, str: " + str); - } - return "hello " + str; - } - } -``` - -增强后的字节码,再反编译: - -```java -package com.example; - -public static class ByteKitDemo.Sample { - private int exceptionCount = 0; - - public String hello(String string, boolean bl) { - try { - String string2 = "(Ljava/lang/String;Z)Ljava/lang/String;"; - String string3 = "hello"; - Object[] arrobject = new Object[]{string, new Boolean(bl)}; - Class class_ = ByteKitDemo.Sample.class; - ByteKitDemo.Sample sample = this; - System.out.println("atEnter, args[0]: " + arrobject[0]); - } - catch (RuntimeException runtimeException) { - Class class_ = ByteKitDemo.Sample.class; - RuntimeException runtimeException2 = runtimeException; - System.out.println("exception handler: " + class_); - runtimeException2.printStackTrace(); - } - try { - String string4; - void str; - void exception; - if (exception != false) { - ++this.exceptionCount; - throw new RuntimeException("test exception, str: " + (String)str); - } - String string5 = string4 = "hello " + (String)str; - System.out.println("atExit, returnObject: " + string5); - return string4; - } - catch (RuntimeException runtimeException) { - int n = this.exceptionCount; - RuntimeException runtimeException3 = runtimeException; - System.out.println("atExceptionExit, ex: " + runtimeException3.getMessage() + ", field exceptionCount: " + n); - throw runtimeException; - } - } -} -``` diff --git a/bytekit/pom.xml b/bytekit/pom.xml deleted file mode 100644 index 37477376e..000000000 --- a/bytekit/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - 4.0.0 - - com.taobao.arthas - arthas-all - ${revision} - ../pom.xml - - arthas-bytekit - arthas-bytekit - - - - com.taobao.arthas - arthas-common - ${project.version} - - - - com.alibaba.arthas - arthas-repackage-asm - - - - org.benf - cfr - provided - true - - - - net.bytebuddy - byte-buddy - provided - true - - - - net.bytebuddy - byte-buddy-agent - provided - true - - - - - junit - junit - test - - - - org.assertj - assertj-core - test - true - - - - org.springframework.boot - spring-boot-starter-test - 1.5.9.RELEASE - test - true - - - com.taobao.arthas - arthas-demo - ${project.version} - test - - - - - - arthas-bytekit - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.6 - 1.6 - UTF-8 - true - - - - - - diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/ByteKit.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/ByteKit.java deleted file mode 100644 index 281ce7431..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/ByteKit.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.taobao.arthas.bytekit; - -import java.util.List; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorClassParser; -import com.taobao.arthas.bytekit.asm.matcher.ClassMatcher; -import com.taobao.arthas.bytekit.asm.matcher.MethodMatcher; - -public class ByteKit { - - - private ClassMatcher classMatcher; - private MethodMatcher methodMatcher; - - private Class interceptorClass; - - private InterceptorClassParser interceptorClassParser; - - private List interceptorProcessors; -} - diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/ClassLoaderAwareClassWriter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/ClassLoaderAwareClassWriter.java deleted file mode 100644 index fb46dbca1..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/ClassLoaderAwareClassWriter.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.taobao.arthas.bytekit.asm; - -import com.alibaba.arthas.deps.org.objectweb.asm.ClassReader; -import com.alibaba.arthas.deps.org.objectweb.asm.ClassWriter; - -/** - * @author vlinux - * @author hengyunabc 2020-05-29 - * - */ -public class ClassLoaderAwareClassWriter extends ClassWriter { - private ClassLoader classLoader; - - public ClassLoaderAwareClassWriter(int flags, ClassLoader loader) { - this(null, flags, loader); - } - - public ClassLoaderAwareClassWriter(ClassReader classReader, int flags, ClassLoader loader) { - super(classReader, flags); - this.classLoader = loader; - } - - /* - * 注意,为了自动计算帧的大小,有时必须计算两个类共同的父类。 - * 缺省情况下,ClassWriter将会在getCommonSuperClass方法中计算这些,通过在加载这两个类进入虚拟机时,使用反射API来计算。 - * 但是,如果你将要生成的几个类相互之间引用,这将会带来问题,因为引用的类可能还不存在。 - * 在这种情况下,你可以重写getCommonSuperClass方法来解决这个问题。 - * - * 通过重写 getCommonSuperClass() 方法,更正获取ClassLoader的方式,改成使用指定ClassLoader的方式进行。 - * 规避了原有代码采用Object.class.getClassLoader()的方式 - */ - @Override - protected String getCommonSuperClass(String type1, String type2) { - Class c, d; - try { - c = Class.forName(type1.replace('/', '.'), false, classLoader); - d = Class.forName(type2.replace('/', '.'), false, classLoader); - } catch (Exception e) { - throw new RuntimeException(e); - } - if (c.isAssignableFrom(d)) { - return type1; - } - if (d.isAssignableFrom(c)) { - return type2; - } - if (c.isInterface() || d.isInterface()) { - return "java/lang/Object"; - } else { - do { - c = c.getSuperclass(); - } while (!c.isAssignableFrom(d)); - return c.getName().replace('.', '/'); - } - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/InliningAdapter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/InliningAdapter.java deleted file mode 100644 index 6ebd30f48..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/InliningAdapter.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.taobao.arthas.bytekit.asm; - -import com.alibaba.arthas.deps.org.objectweb.asm.Label; -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.commons.LocalVariablesSorter; - -/** - * Adapter for to be inlined code. - * - * This adapter does all parameter renaming and replacing of the RETURN opcodes - * - * - */ -public class InliningAdapter extends LocalVariablesSorter { - private final Label end; - private LocalVariablesSorter lvs; - - public InliningAdapter(LocalVariablesSorter mv, int access, String desc, Label end) { - super(Opcodes.ASM9, access, desc, mv); - this.end = end; - this.lvs = mv; - -// int off = (access & Opcodes.ACC_STATIC) != 0 ? -// 0 : 1; -// Type[] args = Type.getArgumentTypes(desc); -// for (int i = args.length - 1; i >= 0; i--) { -// super.visitVarInsn(args[i].getOpcode( -// Opcodes.ISTORE), i + off); -// } -// if (off > 0) { -// super.visitVarInsn(Opcodes.ASTORE, 0); -// } - - // save args to local vars - int off = (access & Opcodes.ACC_STATIC) != 0 ? 0 : 1; - Type[] args = Type.getArgumentTypes(desc); - int argsOff = off; - - for(int i = 0; i < args.length; ++i) { - argsOff += args[i].getSize(); - } - - for(int i = args.length - 1; i >= 0; --i) { - argsOff -= args[i].getSize(); - this.visitVarInsn(args[i].getOpcode(Opcodes.ISTORE), argsOff); - } - - // this - if (off > 0) { - this.visitVarInsn(Opcodes.ASTORE, 0); - } - } - - @Override - public void visitInsn(int opcode) { - if (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) { - super.visitJumpInsn(Opcodes.GOTO, end); - } else { - super.visitInsn(opcode); - } - } - - @Override - public void visitMaxs(int stack, int locals) { -// super.visitMaxs(stack, locals); - } - - @Override - protected int newLocalMapping(Type type) { - return lvs.newLocal(type); - } - - @Override - public void visitVarInsn(int opcode, int var) { - super.visitVarInsn(opcode, var + this.firstLocal); - } - @Override - public void visitIincInsn(int var, int increment) { - super.visitIincInsn(var + this.firstLocal, increment); - } - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { - super.visitLocalVariable(name, desc, signature, start, end, index + this.firstLocal); - } -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodCallInliner.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodCallInliner.java deleted file mode 100644 index dd8cad220..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodCallInliner.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.taobao.arthas.bytekit.asm; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Label; -import com.alibaba.arthas.deps.org.objectweb.asm.MethodVisitor; -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.commons.GeneratorAdapter; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; - -/** - * @author hengyunabc 2018-01-31 - * - */ -public abstract class MethodCallInliner extends GeneratorAdapter { - public class CatchBlock { - - private Label start; - private Label handler; - private String type; - private Label end; - - public CatchBlock(Label start, Label end, Label handler, String type) { - this.start = start; - this.end = end; - this.handler = handler; - this.type = type; - } - - } - - private final MethodNode toBeInlined; - private List blocks = new ArrayList(); - private boolean inlining; - private boolean afterInlining; - - public MethodCallInliner(int access, String name, String desc, MethodVisitor mv, - MethodNode toBeInlined) { - super(Opcodes.ASM9, mv, access, name, desc); - this.toBeInlined = toBeInlined; - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - if (!shouldBeInlined(owner, name, desc)) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - - // if (this.analyzerAdapter != null) { - // mv = new MergeFrameAdapter(this.api, this.analyzerAdapter, - // (MethodVisitor)mv); - // } - - Label end = new Label(); - inlining = true; - toBeInlined.instructions.resetLabels(); - - // pass the to be inlined method through the inlining adapter to this - toBeInlined.accept(new InliningAdapter(this, toBeInlined.access, toBeInlined.desc, end)); - inlining = false; - afterInlining = true; - - // visit the end label - super.visitLabel(end); - - // box the return value if necessary - // Type returnType = - // Type.getMethodType(toBeInlined.desc).getReturnType(); - // valueOf(returnType); - - } - - abstract boolean shouldBeInlined(String owner, String name, String desc); - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - if (!inlining) { - blocks.add(new CatchBlock(start, end, handler, type)); - } else { - super.visitTryCatchBlock(start, end, handler, type); - } - } - - @Override - public void visitMaxs(int stack, int locals) { - for (CatchBlock b : blocks) - super.visitTryCatchBlock(b.start, b.end, b.handler, b.type); - super.visitMaxs(stack, locals); - } - - @Override - public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { - // swallow - } -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodInfo.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodInfo.java deleted file mode 100644 index 8188d4d7d..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodInfo.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.taobao.arthas.bytekit.asm; - -/** - * - * @author hengyunabc 2019-03-18 - * - */ -public class MethodInfo { - - private String owner; - - private int access; - private String name; - private String desc; - - public int getAccess() { - return access; - } - - public void setAccess(int access) { - this.access = access; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodProcessor.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodProcessor.java deleted file mode 100644 index 31030b695..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MethodProcessor.java +++ /dev/null @@ -1,784 +0,0 @@ -package com.taobao.arthas.bytekit.asm; - -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.commons.Method; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.FrameNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.IincInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.IntInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.JumpInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LabelNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LdcInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.TryCatchBlockNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.TypeInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.VarInsnNode; -import com.taobao.arthas.bytekit.asm.location.filter.DefaultLocationFilter; -import com.taobao.arthas.bytekit.asm.location.filter.LocationFilter; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; - -public class MethodProcessor { - - private String owner; - /** - * maybe null - */ - private ClassNode classNode; - private MethodNode methodNode; - - private final Type[] argumentTypes; - private final Type returnType; - - private int nextLocals; - - private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte"); - - private static final Type BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean"); - - private static final Type SHORT_TYPE = Type.getObjectType("java/lang/Short"); - - private static final Type CHARACTER_TYPE = Type.getObjectType("java/lang/Character"); - - private static final Type INTEGER_TYPE = Type.getObjectType("java/lang/Integer"); - - private static final Type FLOAT_TYPE = Type.getObjectType("java/lang/Float"); - - private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long"); - - private static final Type DOUBLE_TYPE = Type.getObjectType("java/lang/Double"); - - private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object"); - - private static final Type STRING_TYPE = Type.getObjectType("java/lang/String"); - - private static final Type THROWABLE_TYPE = Type.getObjectType("java/lang/Throwable"); - - private static final Type NUMBER_TYPE = Type.getObjectType("java/lang/Number"); - - private static final Type OBJECT_ARRAY_TYPE = Type.getType(Object[].class); - - private static final Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()"); - - private static final Method CHAR_VALUE = Method.getMethod("char charValue()"); - - private static final Method INT_VALUE = Method.getMethod("int intValue()"); - - private static final Method FLOAT_VALUE = Method.getMethod("float floatValue()"); - - private static final Method LONG_VALUE = Method.getMethod("long longValue()"); - - private static final Method DOUBLE_VALUE = Method.getMethod("double doubleValue()"); - - public static final String DEFAULT_INNER_VARIABLE_PREFIX = "_$bytekit$_"; - - private final LabelNode interceptorVariableStartLabelNode = new LabelNode(); - private final LabelNode interceptorVariableEndLabelNode = new LabelNode(); - - private AbstractInsnNode enterInsnNode; - // TODO 这里应该直接从 InsnList 里来取?因为插入代码之后,这个会改变的。 - // TODO 这个没有被使用到,是不是没用的?? - private AbstractInsnNode lastInsnNode; - - /** - * 保留中间生成的 variable的名字 - */ - private boolean keepLocalVariableNames; - - private String innerVariablePrefix; - - private String returnVariableName; - private String throwVariableName; - private String invokeArgsVariableName; - private String monitorVariableName; - private LocalVariableNode returnVariableNode = null; - private LocalVariableNode throwVariableNode = null; - private LocalVariableNode invokeArgsVariableNode = null; - private LocalVariableNode monitorVariableNode = null; // for synchronized - - private String invokeReturnVariablePrefix; - private Map invokeReturnVariableNodeMap = new HashMap(); - - private TryCatchBlock tryCatchBlock = null; - - private LocationFilter locationFilter = new DefaultLocationFilter(); - - public MethodProcessor(final ClassNode classNode, final MethodNode methodNode) { - this(classNode, methodNode, false); - } - - public MethodProcessor(final ClassNode classNode, final MethodNode methodNode, LocationFilter locationFilter) { - this(classNode, methodNode, false); - this.locationFilter = locationFilter; - } - - public MethodProcessor(final ClassNode classNode, final MethodNode methodNode, boolean keepLocalVariableNames) { - this(classNode.name, methodNode, keepLocalVariableNames); - this.classNode = classNode; - } - - public MethodProcessor(final String owner, final MethodNode methodNode, boolean keepLocalVariableNames) { - this.owner = owner; - this.methodNode = methodNode; - this.nextLocals = methodNode.maxLocals; - this.argumentTypes = Type.getArgumentTypes(methodNode.desc); - this.returnType = Type.getReturnType(methodNode.desc); - this.keepLocalVariableNames = keepLocalVariableNames; - - // find enter & exit instruction. - if (isConstructor()) { - this.enterInsnNode = findInitConstructorInstruction(); - } else { - this.enterInsnNode = methodNode.instructions.getFirst(); - } - - // when the method is empty, both enterInsnNode and lastInsnNode are Opcodes.RETURN ; - this.lastInsnNode = methodNode.instructions.getLast(); - - // setup interceptor variables start/end label. - this.methodNode.instructions.insertBefore(this.enterInsnNode, this.interceptorVariableStartLabelNode); - this.methodNode.instructions.insert(this.lastInsnNode, this.interceptorVariableEndLabelNode); - - initInnerVariablePrefix(); - } - public MethodProcessor(final String owner, final MethodNode methodNode) { - this(owner, methodNode, false); - } - - private void initInnerVariablePrefix() { - String prefix = DEFAULT_INNER_VARIABLE_PREFIX; - int count = 0; - while(existLocalVariableWithPrefix(prefix)) { - prefix = DEFAULT_INNER_VARIABLE_PREFIX + count + "_"; - count++; - } - this.innerVariablePrefix = prefix; - - returnVariableName = innerVariablePrefix + "_return"; - throwVariableName = innerVariablePrefix + "_throw"; - invokeArgsVariableName = innerVariablePrefix + "_invokeArgs"; - monitorVariableName = innerVariablePrefix + "_monitor"; - - invokeReturnVariablePrefix = innerVariablePrefix + "_invokeReturn_"; - } - - private boolean existLocalVariableWithPrefix(String prefix) { - for (LocalVariableNode variableNode : this.methodNode.localVariables) { - if (variableNode.name.startsWith(prefix)) { - return true; - } - } - return false; - } - - public LocalVariableNode initMonitorVariableNode() { - if (monitorVariableNode == null) { - monitorVariableNode = this.addInterceptorLocalVariable(monitorVariableName, OBJECT_TYPE.getDescriptor()); - } - return monitorVariableNode; - } - - public LocalVariableNode initThrowVariableNode() { - if (throwVariableNode == null) { - throwVariableNode = this.addInterceptorLocalVariable(throwVariableName, THROWABLE_TYPE.getDescriptor()); - } - return throwVariableNode; - } - - public LocalVariableNode initInvokeArgsVariableNode() { - if (invokeArgsVariableNode == null) { - invokeArgsVariableNode = this.addInterceptorLocalVariable(invokeArgsVariableName, - OBJECT_ARRAY_TYPE.getDescriptor()); - } - return invokeArgsVariableNode; - } - - public LocalVariableNode initReturnVariableNode() { - if (returnVariableNode == null) { - returnVariableNode = this.addInterceptorLocalVariable(returnVariableName, returnType.getDescriptor()); - } - return returnVariableNode; - } - - /** - * - * @param name - * @param type - * @return - */ - public LocalVariableNode initInvokeReturnVariableNode(String name, Type type) { - String key = this.invokeReturnVariablePrefix + name; - LocalVariableNode variableNode = invokeReturnVariableNodeMap.get(key); - if (variableNode == null) { - variableNode = this.addInterceptorLocalVariable(key, type.getDescriptor()); - invokeReturnVariableNodeMap.put(key, variableNode); - } - return variableNode; - } - - public TryCatchBlock initTryCatchBlock() { - return initTryCatchBlock(THROWABLE_TYPE.getInternalName()); - } - - public TryCatchBlock initTryCatchBlock(String exception) { - if( this.tryCatchBlock == null) { - this.tryCatchBlock = new TryCatchBlock(methodNode, exception); - this.methodNode.instructions.insertBefore(this.getEnterInsnNode(), tryCatchBlock.getStartLabelNode()); - this.methodNode.instructions.insert(this.getLastInsnNode(), tryCatchBlock.getEndLabelNode()); - InsnList instructions = new InsnList(); - AsmOpUtils.throwException(instructions); - this.methodNode.instructions.insert(tryCatchBlock.getEndLabelNode(), instructions); - - tryCatchBlock.sort(); - } - return tryCatchBlock; - } - - AbstractInsnNode findInitConstructorInstruction() { - int nested = 0; - for (AbstractInsnNode insnNode = this.methodNode.instructions.getFirst(); insnNode != null; insnNode = insnNode - .getNext()) { - if (insnNode instanceof TypeInsnNode) { - if (insnNode.getOpcode() == Opcodes.NEW) { - // new object(). - nested++; - } - } else if (insnNode instanceof MethodInsnNode) { - final MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - if (methodInsnNode.getOpcode() == Opcodes.INVOKESPECIAL && methodInsnNode.name.equals("")) { - if (--nested < 0) { - // find this() or super(). - return insnNode.getNext(); - } - } - } - } - - return null; - } - - public AbstractInsnNode getEnterInsnNode() { - return enterInsnNode; - } - - public AbstractInsnNode getLastInsnNode() { - return lastInsnNode; - } - - public String[] getParameterTypes() { - final String[] parameterTypes = new String[this.argumentTypes.length]; - for (int i = 0; i < this.argumentTypes.length; i++) { - parameterTypes[i] = this.argumentTypes[i].getClassName(); - } - - return parameterTypes; - } - - public String[] getParameterNames() { - if (this.argumentTypes.length == 0) { - return new String[0]; - } - - final List localVariableNodes = this.methodNode.localVariables; - int localVariableStartIndex = 1; - if (isStatic()) { - // static method is none this. - localVariableStartIndex = 0; - } - - if (localVariableNodes == null || localVariableNodes.size() <= localVariableStartIndex - || (this.argumentTypes.length + localVariableStartIndex) > localVariableNodes.size()) { - // make simple argument names. - final String[] names = new String[this.argumentTypes.length]; - for (int i = 0; i < this.argumentTypes.length; i++) { - final String className = this.argumentTypes[i].getClassName(); - if (className != null) { - final int findIndex = className.lastIndexOf('.'); - if (findIndex == -1) { - names[i] = className; - } else { - names[i] = className.substring(findIndex + 1); - } - } else { - names[i] = this.argumentTypes[i].getDescriptor(); - } - } - return names; - } - - // sort by index. - Collections.sort(localVariableNodes, new Comparator() { - - @Override - public int compare(LocalVariableNode o1, LocalVariableNode o2) { - return o1.index - o2.index; - } - }); - String[] names = new String[this.argumentTypes.length]; - - for (int i = 0; i < this.argumentTypes.length; i++) { - final String name = localVariableNodes.get(localVariableStartIndex++).name; - if (name != null) { - names[i] = name; - } else { - names[i] = ""; - } - } - - return names; - } - - public Type getReturnType() { - return this.returnType; - } - - private boolean hasLocalVariable(String name) { - List localVariableNodes = this.methodNode.localVariables; - if (localVariableNodes == null) { - return false; - } - - for (LocalVariableNode node : localVariableNodes) { - if (node.name.equals(name)) { - return true; - } - } - - return false; - } - - public void loadThis(final InsnList instructions) { - if (isConstructor()) { - // load this. - loadVar(instructions, 0); - } else { - if (isStatic()) { - // load null. - loadNull(instructions); - } else { - // load this. - loadVar(instructions, 0); - } - } - } - - void storeVar(final InsnList instructions, final int index) { - instructions.add(new VarInsnNode(Opcodes.ASTORE, index)); - } - - void storeInt(final InsnList instructions, final int index) { - instructions.add(new VarInsnNode(Opcodes.ISTORE, index)); - } - - void loadNull(final InsnList instructions) { - instructions.add(new InsnNode(Opcodes.ACONST_NULL)); - } - - void loadVar(final InsnList instructions, final int index) { - instructions.add(new VarInsnNode(Opcodes.ALOAD, index)); - } - - void loadInt(final InsnList instructions, final int index) { - instructions.add(new VarInsnNode(Opcodes.ILOAD, index)); - } - - boolean isReturnCode(final int opcode) { - return opcode == Opcodes.IRETURN || opcode == Opcodes.LRETURN || opcode == Opcodes.FRETURN - || opcode == Opcodes.DRETURN || opcode == Opcodes.ARETURN || opcode == Opcodes.RETURN; - } - - Type getBoxedType(final Type type) { - switch (type.getSort()) { - case Type.BYTE: - return BYTE_TYPE; - case Type.BOOLEAN: - return BOOLEAN_TYPE; - case Type.SHORT: - return SHORT_TYPE; - case Type.CHAR: - return CHARACTER_TYPE; - case Type.INT: - return INTEGER_TYPE; - case Type.FLOAT: - return FLOAT_TYPE; - case Type.LONG: - return LONG_TYPE; - case Type.DOUBLE: - return DOUBLE_TYPE; - } - return type; - } - - void push(InsnList insnList, final int value) { - if (value >= -1 && value <= 5) { - insnList.add(new InsnNode(Opcodes.ICONST_0 + value)); - } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { - insnList.add(new IntInsnNode(Opcodes.BIPUSH, value)); - } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { - insnList.add(new IntInsnNode(Opcodes.SIPUSH, value)); - } else { - insnList.add(new LdcInsnNode(value)); - } - } - - void push(InsnList insnList, final String value) { - if (value == null) { - insnList.add(new InsnNode(Opcodes.ACONST_NULL)); - } else { - insnList.add(new LdcInsnNode(value)); - } - } - - void newArray(final InsnList insnList, final Type type) { - insnList.add(new TypeInsnNode(Opcodes.ANEWARRAY, type.getInternalName())); - } - - void dup(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP)); - } - - void dup2(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP2)); - } - - void dupX1(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP_X1)); - } - - void dupX2(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP_X2)); - } - - void pop(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.POP)); - } - - void swap(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.SWAP)); - } - - void loadArgsVar(final InsnList instructions) { - if (this.argumentTypes.length == 0) { - // null. - loadNull(instructions); - return; - } - - push(instructions, this.argumentTypes.length); - // new array - newArray(instructions, OBJECT_TYPE); - for (int i = 0; i < this.argumentTypes.length; i++) { - Type type = this.argumentTypes[i]; - dup(instructions); - push(instructions, i); - // loadArg - loadArg(instructions, this.argumentTypes, i); - // box - box(instructions, type); - // arrayStore - arrayStore(instructions, OBJECT_TYPE); - } - } - - void loadArgs(final InsnList instructions) { - for (int i = 0; i < this.argumentTypes.length; i++) { - loadArg(instructions, this.argumentTypes, i); - } - } - - void loadArg(final InsnList instructions, Type[] argumentTypes, int i) { - final int index = getArgIndex(argumentTypes, i); - final Type type = argumentTypes[i]; - instructions.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), index)); - } - - int getArgIndex(final Type[] argumentTypes, final int arg) { - int index = isStatic() ? 0 : 1; - for (int i = 0; i < arg; i++) { - index += argumentTypes[i].getSize(); - } - return index; - } - - void box(final InsnList instructions, Type type) { - if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { - return; - } - - if (type == Type.VOID_TYPE) { - // push null - instructions.add(new InsnNode(Opcodes.ACONST_NULL)); - } else { - Type boxed = getBoxedType(type); - // new instance. - newInstance(instructions, boxed); - if (type.getSize() == 2) { - // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o - // dupX2 - dupX2(instructions); - // dupX2 - dupX2(instructions); - // pop - pop(instructions); - } else { - // p -> po -> opo -> oop -> o - // dupX1 - dupX1(instructions); - // swap - swap(instructions); - } - invokeConstructor(instructions, boxed, new Method("", Type.VOID_TYPE, new Type[] { type })); - } - } - - void unbox(final InsnList instructions, Type type) { - Type t = NUMBER_TYPE; - Method sig = null; - switch (type.getSort()) { - case Type.VOID: - return; - case Type.CHAR: - t = CHARACTER_TYPE; - sig = CHAR_VALUE; - break; - case Type.BOOLEAN: - t = BOOLEAN_TYPE; - sig = BOOLEAN_VALUE; - break; - case Type.DOUBLE: - sig = DOUBLE_VALUE; - break; - case Type.FLOAT: - sig = FLOAT_VALUE; - break; - case Type.LONG: - sig = LONG_VALUE; - break; - case Type.INT: - case Type.SHORT: - case Type.BYTE: - sig = INT_VALUE; - } - if (sig == null) { - instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, type.getInternalName())); - } else { - instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, t.getInternalName())); - instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, t.getInternalName(), sig.getName(), - sig.getDescriptor(), false)); - } - } - - void arrayStore(final InsnList instructions, final Type type) { - instructions.add(new InsnNode(type.getOpcode(Opcodes.IASTORE))); - } - - void arrayLoad(final InsnList instructions, final Type type) { - instructions.add(new InsnNode(type.getOpcode(Opcodes.IALOAD))); - } - - void newInstance(final InsnList instructions, final Type type) { - instructions.add(new TypeInsnNode(Opcodes.NEW, type.getInternalName())); - } - - void invokeConstructor(final InsnList instructions, final Type type, final Method method) { - String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName(); - instructions - .add(new MethodInsnNode(Opcodes.INVOKESPECIAL, owner, method.getName(), method.getDescriptor(), false)); - } - - LocalVariableNode addInterceptorLocalVariable(final String name, final String desc) { - return addLocalVariable(name, desc, this.interceptorVariableStartLabelNode, - this.interceptorVariableEndLabelNode); - } - - LocalVariableNode addLocalVariable(final String name, final String desc, final LabelNode start, - final LabelNode end) { - Type type = Type.getType(desc); - int index = this.nextLocals; - this.nextLocals += type.getSize(); - methodNode.maxLocals = this.nextLocals; - final LocalVariableNode node = new LocalVariableNode(name, desc, null, start, end, index); - if (keepLocalVariableNames) { - this.methodNode.localVariables.add(node); - } - - return node; - } - - public void returnValue(final InsnList instructions) { - instructions.add(new InsnNode(this.returnType.getOpcode(Opcodes.IRETURN))); - } - - public boolean isStatic() { - return (this.methodNode.access & Opcodes.ACC_STATIC) != 0; - } - - public boolean isConstructor() { - return this.methodNode.name != null && this.methodNode.name.equals(""); - } - - public MethodNode getMethodNode() { - return methodNode; - } - - public void setMethodNode(MethodNode methodNode) { - this.methodNode = methodNode; - } - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - - public ClassNode getClassNode() { - return classNode; - } - public void setClassNode(ClassNode classNode) { - this.classNode = classNode; - } - public LocationFilter getLocationFilter() { - return locationFilter; - } - - /** - * TODO 可以考虑实现修改值的功能,原理是传入的 args实际转化为一个stack上的slot,只要在inline之后,把 stack上面的对应的slot保存到想要保存的位置就可以了。 - * @param owner - * @param tmpToInlineMethodNode - */ - public void inline(String owner, MethodNode toInlineMethodNode) { - - ListIterator originMethodIter = this.methodNode.instructions.iterator(); - - while(originMethodIter.hasNext()) { - AbstractInsnNode originMethodInsnNode = originMethodIter.next(); - - if (originMethodInsnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) originMethodInsnNode; - if (methodInsnNode.owner.equals(owner) && methodInsnNode.name.equals(toInlineMethodNode.name) - && methodInsnNode.desc.equals(toInlineMethodNode.desc)) { - // 要copy一份,否则inline多次会出问题 - MethodNode tmpToInlineMethodNode = AsmUtils.copy(toInlineMethodNode); - tmpToInlineMethodNode = AsmUtils.removeLineNumbers(tmpToInlineMethodNode); - - LabelNode end = new LabelNode(); - this.methodNode.instructions.insert(methodInsnNode, end); - - InsnList instructions = new InsnList(); - - // 要先记录好当前的 maxLocals ,然后再依次把 栈上的 args保存起来 ,后面调整 VarInsnNode index里,要加上当前的 maxLocals - // save args to local vars - int currentMaxLocals = this.nextLocals; - - int off = (tmpToInlineMethodNode.access & Opcodes.ACC_STATIC) != 0 ? 0 : 1; - Type[] args = Type.getArgumentTypes(tmpToInlineMethodNode.desc); - int argsOff = off; - - for(int i = 0; i < args.length; ++i) { - argsOff += args[i].getSize(); - } - // 记录新的 maxLocals - this.nextLocals += argsOff; - methodNode.maxLocals = this.nextLocals; - - - for(int i = args.length - 1; i >= 0; --i) { - argsOff -= args[i].getSize(); -// this.visitVarInsn(args[i].getOpcode(Opcodes.ISTORE), argsOff); - - AsmOpUtils.storeVar(instructions, args[i], currentMaxLocals + argsOff); - } - - // this - if (off > 0) { -// this.visitVarInsn(Opcodes.ASTORE, 0); - AsmOpUtils.storeVar(instructions, OBJECT_TYPE, currentMaxLocals); - } - - - ListIterator inlineIterator = tmpToInlineMethodNode.instructions.iterator(); - while(inlineIterator.hasNext()) { - AbstractInsnNode abstractInsnNode = inlineIterator.next(); - if(abstractInsnNode instanceof FrameNode) { - continue; - } - - //修改inline代码中的使用到局部变量的指令的var操作数(变量slot) - if(abstractInsnNode instanceof VarInsnNode) { - VarInsnNode varInsnNode = (VarInsnNode) abstractInsnNode; - varInsnNode.var += currentMaxLocals; - } else if (abstractInsnNode instanceof IincInsnNode) { - IincInsnNode iincInsnNode = (IincInsnNode) abstractInsnNode; - iincInsnNode.var += currentMaxLocals; - } - - int opcode = abstractInsnNode.getOpcode(); - if (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) { -// super.visitJumpInsn(Opcodes.GOTO, end); -// instructions.add(new JumpInsnNode(Opcodes.GOTO, end)); - inlineIterator.remove(); - instructions.add(new JumpInsnNode(Opcodes.GOTO, end)); - continue; - } - inlineIterator.remove(); - instructions.add(abstractInsnNode); - } - - - // 插入inline之后的代码,再删除掉原来的 MethodInsnNode - this.methodNode.instructions.insertBefore(methodInsnNode, instructions); - originMethodIter.remove(); - // try catch 块加上,然后排序 - if(this.methodNode.tryCatchBlocks != null && tmpToInlineMethodNode.tryCatchBlocks != null) { - this.methodNode.tryCatchBlocks.addAll(tmpToInlineMethodNode.tryCatchBlocks); - } - this.sortTryCatchBlock(); - } - } - } - - } - - public void sortTryCatchBlock() { - if (this.methodNode.tryCatchBlocks == null) { - return; - } - - // Compares TryCatchBlockNodes by the length of their "try" block. - Collections.sort(this.methodNode.tryCatchBlocks, new Comparator() { - @Override - public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) { - int len1 = blockLength(t1); - int len2 = blockLength(t2); - return len1 - len2; - } - - private int blockLength(TryCatchBlockNode block) { - final int startidx = methodNode.instructions.indexOf(block.start); - final int endidx = methodNode.instructions.indexOf(block.end); - return endidx - startidx; - } - }); - - // Updates the 'target' of each try catch block annotation. - for (int i = 0; i < this.methodNode.tryCatchBlocks.size(); i++) { - this.methodNode.tryCatchBlocks.get(i).updateIndex(i); - } - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MyTryCatchBlock.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MyTryCatchBlock.java deleted file mode 100644 index 3c90ec99d..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/MyTryCatchBlock.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.taobao.arthas.bytekit.asm; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LabelNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.TryCatchBlockNode; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -public class MyTryCatchBlock { - private final MethodNode methodNode; - private final LabelNode startLabelNode = new LabelNode(); - private final LabelNode endLabelNode = new LabelNode(); - private final LabelNode handlerLabelNode = new LabelNode(); - - public MyTryCatchBlock(final MethodNode methodNode) { - this.methodNode = methodNode; - - final TryCatchBlockNode tryCatchBlockNode = new TryCatchBlockNode(this.startLabelNode, this.endLabelNode, this.handlerLabelNode, "java/lang/Throwable"); - if (this.methodNode.tryCatchBlocks == null) { - this.methodNode.tryCatchBlocks = new ArrayList(); - } - this.methodNode.tryCatchBlocks.add(tryCatchBlockNode); - } - - public LabelNode getStartLabelNode() { - return this.startLabelNode; - } - - public LabelNode getEndLabelNode() { - return this.endLabelNode; - } - - public LabelNode getHandlerLabelNode() { - return this.handlerLabelNode; - } - - public void sort() { - if (this.methodNode.tryCatchBlocks == null) { - return; - } - - // Compares TryCatchBlockNodes by the length of their "try" block. - Collections.sort(this.methodNode.tryCatchBlocks, new Comparator() { - @Override - public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) { - int len1 = blockLength(t1); - int len2 = blockLength(t2); - return len1 - len2; - } - - private int blockLength(TryCatchBlockNode block) { - final int startidx = methodNode.instructions.indexOf(block.start); - final int endidx = methodNode.instructions.indexOf(block.end); - return endidx - startidx; - } - }); - - // Updates the 'target' of each try catch block annotation. - for (int i = 0; i < this.methodNode.tryCatchBlocks.size(); i++) { - this.methodNode.tryCatchBlocks.get(i).updateIndex(i); - } - } -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/TryCatchBlock.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/TryCatchBlock.java deleted file mode 100644 index 9068fa2aa..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/TryCatchBlock.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.taobao.arthas.bytekit.asm; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LabelNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.TryCatchBlockNode; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -public class TryCatchBlock { - private final MethodNode methodNode; - private final LabelNode startLabelNode = new LabelNode(); - private final LabelNode endLabelNode = new LabelNode(); - - public TryCatchBlock(final MethodNode methodNode) { - this(methodNode, Type.getType(Throwable.class).getInternalName()); - } - - public TryCatchBlock(final MethodNode methodNode, String exception) { - this.methodNode = methodNode; - - final TryCatchBlockNode tryCatchBlockNode = new TryCatchBlockNode(this.startLabelNode, this.endLabelNode, - this.endLabelNode, exception); - if (this.methodNode.tryCatchBlocks == null) { - this.methodNode.tryCatchBlocks = new ArrayList(); - } - this.methodNode.tryCatchBlocks.add(tryCatchBlockNode); - } - - public LabelNode getStartLabelNode() { - return this.startLabelNode; - } - - public LabelNode getEndLabelNode() { - return this.endLabelNode; - } - - public void sort() { - if (this.methodNode.tryCatchBlocks == null) { - return; - } - - // Compares TryCatchBlockNodes by the length of their "try" block. - Collections.sort(this.methodNode.tryCatchBlocks, new Comparator() { - @Override - public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) { - int len1 = blockLength(t1); - int len2 = blockLength(t2); - return len1 - len2; - } - - private int blockLength(TryCatchBlockNode block) { - final int startidx = methodNode.instructions.indexOf(block.start); - final int endidx = methodNode.instructions.indexOf(block.end); - return endidx - startidx; - } - }); - - // Updates the 'target' of each try catch block annotation. - for (int i = 0; i < this.methodNode.tryCatchBlocks.size(); i++) { - this.methodNode.tryCatchBlocks.get(i).updateIndex(i); - } - } -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/TypeHelper.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/TypeHelper.java deleted file mode 100644 index 0e8d35f80..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/TypeHelper.java +++ /dev/null @@ -1,431 +0,0 @@ -/* -* JBoss, Home of Professional Open Source -* Copyright 2008-10 Red Hat and individual contributors -* by the @authors tag. See the copyright.txt in the distribution for a -* full listing of individual contributors. -* -* This is free software; you can redistribute it and/or modify it -* under the terms of the GNU Lesser General Public License as -* published by the Free Software Foundation; either version 2.1 of -* the License, or (at your option) any later version. -* -* This software is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this software; if not, write to the Free -* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -* 02110-1301 USA, or see the FSF site: http://www.fsf.org. -* -* @authors Andrew Dinn -*/ -package com.taobao.arthas.bytekit.asm; - -/** - * Helpoer class providing static methods for manipulating type and class names, - * field and method descriptor names etc - */ -public class TypeHelper { - - public static boolean equalDescriptors(String desc1, String desc2) - { - int idx1 = 0, idx2 = 0; - int len1 = desc1.length(), len2 = desc2.length(); - while (idx1 < len1) { - // check the other has not dropped off the end - if (idx2 == len2) { - if ((idx1 == (len1 - 1)) && (desc1.charAt(idx1) == '$')) { - return true; - } - return false; - } - // check type is the same - char char1 = desc1.charAt(idx1); - char char2 = desc2.charAt(idx2); - // if we have a $ at the end of the descriptor then this means any return - // type so special case this - if ((char1 == '$' && idx1 == len1 - 1) || (char2 == '$' && idx2 == len2 - 1)) { - return true; - } - // otherwise the chars must match - if (char1 != char2) { - return false; - } - // however an L indicates a class name and we allow a classname without a package - // to match a class name with a package - if (char1 == 'L') { - // ok, ensure the names must match modulo a missing package - int end1 = idx1 + 1; - int end2 = idx2 + 1; - while (end1 < len1 && desc1.charAt(end1) != ';') { - end1++; - } - while (end2 < len2 && desc2.charAt(end2) != ';') { - end2++; - } - if (end1 == len1 || end2 == len2) { - // bad format for desc!! - return false; - } - String typeName1 = desc1.substring(idx1 + 1, end1); - String typeName2 = desc2.substring(idx2 + 1, end2); - if (!typeName1.equals(typeName2)) { - int tailIdx1 = typeName1.lastIndexOf('/'); - int tailIdx2 = typeName2.lastIndexOf('/'); - if (tailIdx1 > 0) { - if (tailIdx2 > 0) { - // both specify packages so they must be different types - return false; - } else { - // only type 1 specifies a package so type 2 should match the tail - if (!typeName2.equals(typeName1.substring(tailIdx1 + 1))) { - return false; - } - } - } else { - if (tailIdx2 > 0) { - // only type 2 specifies a package so type 1 should match the tail - if (!typeName1.equals(typeName2.substring(tailIdx2 + 1))) { - return false; - } - } else { - // neither specify packages so they must be different types - return false; - } - } - } - // skp past ';'s - idx1 = end1; - idx2 = end2; - } - idx1++; - idx2++; - } - - // check the other has not reached the end - if (idx2 != len2) { - return false; - } - - return true; - } - /** - * convert a classname from canonical form to the form used to represent it externally i.e. replace - * all dots with slashes - * - * @param className the canonical name - * @return the external name - */ - public static String externalizeClass(String className) - { - return className.replace('.', '/'); - } - - /** - * convert a classname from external form to canonical form i.e. replace - * all slashes with dots - * - * @param className the external name - * @return the canonical name - */ - public static String internalizeClass(String className) - { - String result = className; - int length = result.length(); - if (result.charAt(length - 1) == ';') { - result = result.substring(1, length - 2); - } - result = result.replace('/', '.'); - return result; - } - - /** - * convert a type name from canonical form to the form used to represent it externally i.e. - * replace primitive type names by the appropriate single letter types, class names - * by the externalized class name bracketed by 'L' and ';' and array names by the - * base type name preceded by '['. - * - * @param typeName the type name - * @return the external name - */ - public static String externalizeType(String typeName) - { - String externalName = ""; - String[] typeAndArrayIndices = typeName.split("\\["); - String baseType = typeAndArrayIndices[0].trim(); - for (int i = 1; i< typeAndArrayIndices.length; i++) { - String arrayIdx = typeAndArrayIndices[i]; - if (arrayIdx.indexOf("\\]") != 0) { - externalName += '['; - } - } - for (int i = 0; i < internalNames.length; i++) { - if (internalNames[i].equals(baseType)) { - externalName += externalNames[i]; - return externalName; - } - } - - externalName += "L" + externalizeClass(baseType) + ";"; - - return externalName; - } - - /** - * list of well known typenames as written in Java code - */ - final static private String[] internalNames = { - "", /* equivalent to void */ - "void", - "byte", - "char", - "short", - "int", - "long", - "float", - "double", - "boolean", - "Byte", - "Character", - "Short", - "Integer", - "Long", - "Float", - "Double", - "String", - "java.lang.Byte", - "java.lang.Character", - "java.lang.Short", - "java.lang.Integer", - "java.lang.Long", - "java.lang.Float", - "java.lang.Double", - "java.lang.String" - }; - - /** - * list of typenames in external form corresponding to entries ni previous list - */ - final static private String[] externalNames = { - "$", - "V", - "B", - "C", - "S", - "I", - "J", - "F", - "D", - "Z", - "Ljava/lang/Byte;", - "Ljava/lang/Character;", - "Ljava/lang/Short;", - "Ljava/lang/Integer;", - "Ljava/lang/Long;", - "Ljava/lang/Float;", - "Ljava/lang/Double;", - "Ljava/lang/String;", - "Ljava/lang/Byte;", - "Ljava/lang/Character;", - "Ljava/lang/Short;", - "Ljava/lang/Integer;", - "Ljava/lang/Long;", - "Ljava/lang/Float;", - "Ljava/lang/Double;", - "Ljava/lang/String;" - }; - - /** - * convert a method descriptor from canonical form to the form used to represent it externally - * - * @param desc the method descriptor which must be trimmed of any surrounding white space - * @return an externalised form for the descriptor - */ - public static String externalizeDescriptor(String desc) - { - // the descriptor will start with '(' and the arguments list should end with ')' and, - // if it is not void be followed by a return type - int openIdx = desc.indexOf('('); - int closeIdx = desc.indexOf(')'); - int length = desc.length(); - if (openIdx != 0) { - return ""; - } - if (closeIdx < 0) { - return ""; - } - String retType = (closeIdx < length ? desc.substring(closeIdx + 1).trim() : ""); - String externalRetType = externalizeType(retType); - String argString = desc.substring(1, closeIdx).trim(); - String externalArgs = ""; - if (argString.equals("")) { - externalArgs = argString; - } else { - String[] args = desc.substring(1, closeIdx).trim().split(","); - for (int i = 0; i < args.length ; i++) { - externalArgs += externalizeType(args[i]); - } - } - - return "(" + externalArgs + ")" + externalRetType; - } - - /** - * convert a method descriptor from the form used to represent it externally to canonical form - * - * @param desc the method descriptor which must be trimmed of any surrounding white space and start with "(". - * it must end either with ")" or with ") " followed by an exernalized return type - * @return an internalised form for the descriptor, possibly followed by a space and externalized return type - */ - public static String internalizeDescriptor(String desc) - { - StringBuffer buffer = new StringBuffer(); - String sepr = ""; - int argStart = desc.indexOf('('); - int argEnd = desc.indexOf(')'); - int max = desc.length(); - if (argStart < 0 || argEnd < 0) { - return "(...)"; - } - int arrayCount = 0; - boolean addSepr = false; - - buffer.append("("); - - for (int idx = argStart + 1; idx < max;) { - char next = desc.charAt(idx); - if (addSepr) { - while (arrayCount > 0) { - buffer.append("[]"); - arrayCount--; - } - buffer.append(sepr); - } - addSepr = true; - switch(next) { - case 'B': - { - buffer.append("byte"); - } - break; - case 'C': - { - buffer.append("char"); - } - break; - case 'S': - { - buffer.append("short"); - } - break; - case 'I': - { - buffer.append("int"); - } - break; - case 'J': - { - buffer.append("long"); - } - break; - case 'Z': - { - buffer.append("boolean"); - } - break; - case 'F': - { - buffer.append("float"); - } - break; - case 'D': - { - buffer.append("double"); - } - case 'V': - { - buffer.append("void"); - } - break; - case 'L': - { - int tailIdx = idx+1; - while (tailIdx < max) { - char tailChar = desc.charAt(tailIdx); - if (tailChar == ';') { - break; - } - if (tailChar == '/') - { - tailChar = '.'; - } - buffer.append(tailChar); - tailIdx++; - } - idx = tailIdx; - } - break; - case '[': - { - arrayCount++; - addSepr = false; - } - break; - case ')': - { - if (idx == argEnd - 1) { - buffer.append(")"); - } else { - // leave room for return type - buffer.append(") "); - } - addSepr = false; - } - break; - default: - { - addSepr = false; - } - } - idx++; - if (idx < argEnd) { - sepr = ","; - } else { - sepr = ""; - } - } - - return buffer.toString(); - } - - /** - * split off the method name preceding the signature and return it - * @param targetMethod - the unqualified method name, possibly including signature - * @return the method name - */ - public static String parseMethodName(String targetMethod) { - int sigIdx = targetMethod.indexOf("("); - if (sigIdx > 0) { - return targetMethod.substring(0, sigIdx).trim(); - } else { - return targetMethod; - } - } - - /** - * split off the signature following the method name and return it - * @param targetMethod - the unqualified method name, possibly including signature - * @return the signature - */ - public static String parseMethodDescriptor(String targetMethod) { - int descIdx = targetMethod.indexOf("("); - if (descIdx >= 0) { - String desc = targetMethod.substring(descIdx, targetMethod.length()).trim(); - return externalizeDescriptor(desc); - } else { - return ""; - } - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArgNamesBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArgNamesBinding.java deleted file mode 100644 index b752daf1c..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArgNamesBinding.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -public class ArgNamesBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - - String[] parameterNames = bindingContext.getMethodProcessor().getParameterNames(); - - AsmOpUtils.push(instructions, parameterNames.length); - AsmOpUtils.newArray(instructions, AsmOpUtils.STRING_TYPE); - - for(int i = 0; i < parameterNames.length; ++i) { - AsmOpUtils.dup(instructions); - - AsmOpUtils.push(instructions, i); - AsmOpUtils.push(instructions, parameterNames[i]); - - AsmOpUtils.arrayStore(instructions, AsmOpUtils.STRING_TYPE); - } - } - - @Override - public Type getType(BindingContext bindingContext) { - return AsmOpUtils.STRING_ARRAY_TYPE; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArgsBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArgsBinding.java deleted file mode 100644 index 21f3bc20b..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArgsBinding.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -public class ArgsBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - AsmOpUtils.loadArgArray(instructions, bindingContext.getMethodProcessor().getMethodNode()); - } - - @Override - public Type getType(BindingContext bindingContext) { - return AsmOpUtils.OBJECT_ARRAY_TYPE; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArrayBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArrayBinding.java deleted file mode 100644 index 363ef8928..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ArrayBinding.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * TODO 这个判断是否要从stack上取数据,要看 其它的binding是否需要。 是否 optional,这个应该是由 ArrayBinding 整体设定?? - * @author hengyunabc - * - */ -public class ArrayBinding extends Binding{ - - // TODO 数组的 type是什么? -// private Type type; - - List bindingList = new ArrayList(); - - public ArrayBinding(List bindingList) { - this.bindingList = bindingList; - } - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - AsmOpUtils.push(instructions, bindingList.size()); - AsmOpUtils.newArray(instructions, AsmOpUtils.OBJECT_TYPE); - - for(int i = 0; i < bindingList.size(); ++i) { - AsmOpUtils.dup(instructions); - - AsmOpUtils.push(instructions, i); - Binding binding = bindingList.get(i); - binding.pushOntoStack(instructions, bindingContext); - AsmOpUtils.box(instructions, binding.getType(bindingContext)); - - AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE); - } - } - - @Override - public Type getType(BindingContext bindingContext) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/Binding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/Binding.java deleted file mode 100644 index 24b99cdef..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/Binding.java +++ /dev/null @@ -1,424 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -import com.taobao.arthas.bytekit.asm.binding.annotation.BindingParser; -import com.taobao.arthas.bytekit.asm.binding.annotation.BindingParserHandler; - - -public abstract class Binding { - - /** - * 是否可选的,当不符合条件,或者获取不到值时,会转为 null,这个不支持原始类型,就像java.util.Optional 一样? - * @return - */ - public boolean optional() { - return false; - } - - /** - * 检查当前条件下这个binding是否可以工作,比如检查field是否有这个field。 - * @return - */ - public boolean check(BindingContext bindingContext) { - return true; - } - - /** - * 把这个binding本身放到栈上 - * @param instructions - * @param bindingContext - */ - public abstract void pushOntoStack(InsnList instructions, BindingContext bindingContext); - - public abstract Type getType( BindingContext bindingContext); - - public boolean fromStack() { - return false; - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = ArgsBindingParser.class) - public static @interface Args { - - boolean optional() default false; - - } - public static class ArgsBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new ArgsBinding(); - } - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = ArgNamesBindingParser.class) - public static @interface ArgNames { - - boolean optional() default false; - - } - public static class ArgNamesBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new ArgNamesBinding(); - } - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = LocalVarsBindingParser.class) - public static @interface LocalVars { - - boolean optional() default false; - - } - public static class LocalVarsBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new LocalVarsBinding(); - } - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = LocalVarNamesBindingParser.class) - public static @interface LocalVarNames { - - boolean optional() default false; - - } - public static class LocalVarNamesBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new LocalVarNamesBinding(); - } - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = ClassBindingParser.class) - public static @interface Class { - - boolean optional() default false; - - } - - public static class ClassBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new ClassBinding(); - } - - } - - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = FieldBindingParser.class) - public static @interface Field { - boolean optional() default false; - java.lang.Class owner() default Void.class; - java.lang.Class type() default Void.class; - String name(); - boolean isStatic() default false; - boolean box() default false; - } - - public static class FieldBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - Field field = (Field) annotation; - Type ownerType = Type.getType(field.owner()); - if(field.owner().equals(Void.class)) { - ownerType = null; - } - Type fieldType = Type.getType(field.type()); - if(field.type().equals(Void.class)) { - fieldType = null; - } - return new FieldBinding(ownerType, field.name(), fieldType, - field.isStatic(), field.box()); - } - } - - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = InvokeArgsBindingParser.class) - public static @interface InvokeArgs { - - boolean optional() default false; - - } - - public static class InvokeArgsBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new InvokeArgsBinding(); - } - } - - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = InvokeReturnBindingParser.class) - public static @interface InvokeReturn { - - boolean optional() default false; - - } - - public static class InvokeReturnBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new InvokeReturnBinding(); - } - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = InvokeMethodNameBindingParser.class) - public static @interface InvokeMethodName { - - boolean optional() default false; - - } - - public static class InvokeMethodNameBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new InvokeMethodNameBinding(); - } - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = InvokeMethodOwnerBindingParser.class) - public static @interface InvokeMethodOwner { - - boolean optional() default false; - - } - - public static class InvokeMethodOwnerBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new InvokeMethodOwnerBinding(); - } - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = InvokeMethodDeclarationBindingParser.class) - public static @interface InvokeMethodDeclaration { - - boolean optional() default false; - - } - - public static class InvokeMethodDeclarationBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new InvokeMethodDeclarationBinding(); - } - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = InvokeInfoBindingParser.class) - public static @interface InvokeInfo { - - boolean optional() default false; - - } - - public static class InvokeInfoBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new InvokeInfoBinding(); - } - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = MethodBindingParser.class) - public static @interface Method { - boolean optional() default false; - } - - public static class MethodBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new MethodBinding(); - } - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = MethodNameBindingParser.class) - public static @interface MethodName { - boolean optional() default false; - } - - public static class MethodNameBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new MethodNameBinding(); - } - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = MethodDescBindingParser.class) - public static @interface MethodDesc { - boolean optional() default false; - } - - public static class MethodDescBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new MethodDeclarationBinding(); - } - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = MethodInfoBindingParser.class) - public static @interface MethodInfo { - boolean optional() default false; - } - - public static class MethodInfoBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new MethodInfoBinding(); - } - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = ReturnBindingParser.class) - public static @interface Return { - - boolean optional() default false; - - } - - public static class ReturnBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new ReturnBinding(); - } - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = ThisBindingParser.class) - public static @interface This { - - } - - public static class ThisBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new ThisBinding(); - } - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = ThrowableBindingParser.class) - public static @interface Throwable { - - boolean optional() default false; - - } - - public static class ThrowableBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new ThrowableBinding(); - } - - } - - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = LineBindingParser.class) - public static @interface Line { - boolean optional() default false; - - /** - * 是否精确是在某个 LineNumberNode 上。如果为true的话,会向上找到最接近的 LineNumberNode - * - * @return - */ - boolean exact() default false; - - } - - public static class LineBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - Line line = (Line) annotation; - return new LineBinding(line.exact()); - } - } - - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Target(ElementType.PARAMETER) - @BindingParserHandler(parser = MonitorBindingParser.class) - public static @interface Monitor { - - boolean optional() default false; - - } - - public static class MonitorBindingParser implements BindingParser { - @Override - public Binding parse(Annotation annotation) { - return new MonitorBinding(); - } - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/BindingContext.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/BindingContext.java deleted file mode 100644 index 2fcfb3bed..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/BindingContext.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.location.Location; - -public class BindingContext { - private MethodProcessor methodProcessor; - private Location location; - private StackSaver stackSaver; - - public BindingContext(Location location, MethodProcessor methodProcessor, StackSaver stackSaver) { - this.location = location; - this.methodProcessor = methodProcessor; - this.stackSaver = stackSaver; - } - - public MethodProcessor getMethodProcessor() { - return methodProcessor; - } - - public void setMethodProcessor(MethodProcessor methodProcessor) { - this.methodProcessor = methodProcessor; - } - - public Location getLocation() { - return location; - } - - public void setLocation(Location location) { - this.location = location; - } - - public StackSaver getStackSaver() { - return stackSaver; - } - - public void setStackSaver(StackSaver stackSaver) { - this.stackSaver = stackSaver; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ClassBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ClassBinding.java deleted file mode 100644 index 360afcf75..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ClassBinding.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -public class ClassBinding extends Binding{ - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - String owner = bindingContext.getMethodProcessor().getOwner(); - AsmOpUtils.ldc(instructions, Type.getObjectType(owner)); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(Class.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/FieldBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/FieldBinding.java deleted file mode 100644 index 9c20b2664..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/FieldBinding.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.FieldNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; - -public class FieldBinding extends Binding { - /** - * maybe null - */ - private Type owner; - - private boolean box = false; - - private String name; - - private boolean isStatic = false; - - /** - * maybe null - */ - private Type type; - - public FieldBinding(Type owner, String name, Type type, boolean isStatic, boolean box) { - this.owner = owner; - this.name = name; - this.isStatic = isStatic; - this.box = box; - this.type = type; - } - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - Type onwerType = owner; - Type fieldType = type; - boolean fieldIsStatic = isStatic; - if (owner == null) { - onwerType = Type.getObjectType(bindingContext.getMethodProcessor().getOwner()); - } - // 当type是null里,需要从ClassNode里查找到files,确定type - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - if (fieldType == null) { - ClassNode classNode = methodProcessor.getClassNode(); - if (classNode == null) { - throw new IllegalArgumentException( - "classNode is null, cann not get owner type. FieldBinding name:" + name); - } - FieldNode field = AsmUtils.findField(classNode.fields, name); - if (field == null) { - throw new IllegalArgumentException("can not find field in ClassNode. FieldBinding name:" + name); - } - fieldType = Type.getType(field.desc); - if ((field.access & Opcodes.ACC_STATIC) != 0) { - fieldIsStatic = true; - }else { - fieldIsStatic = false; - } - } - - if (fieldIsStatic) { - AsmOpUtils.getStatic(instructions, onwerType, name, fieldType); - } else { - methodProcessor.loadThis(instructions); - AsmOpUtils.getField(instructions, onwerType, name, fieldType); - } - if (box) { - AsmOpUtils.box(instructions, fieldType); - } - } - - @Override - public Type getType(BindingContext bindingContext) { - Type fieldType = type; - if (fieldType == null) { - ClassNode classNode = bindingContext.getMethodProcessor().getClassNode(); - if (classNode == null) { - throw new IllegalArgumentException( - "classNode is null, cann not get owner type. FieldBinding name:" + name); - } - FieldNode field = AsmUtils.findField(classNode.fields, name); - if (field == null) { - throw new IllegalArgumentException("can not find field in ClassNode. FieldBinding name:" + name); - } - fieldType = Type.getType(field.desc); - } - return fieldType; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/IntBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/IntBinding.java deleted file mode 100644 index 7400da633..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/IntBinding.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -public class IntBinding extends Binding { - - private int value; - - private boolean box = true; - - public IntBinding(int value) { - this(value, true); - } - - public IntBinding(int value, boolean box) { - this.value = value; - this.box = box; - } - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - AsmOpUtils.push(instructions, value); - if (box) { - AsmOpUtils.box(instructions, Type.INT_TYPE); - } - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.INT_TYPE; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeArgsBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeArgsBinding.java deleted file mode 100644 index 4561a0e12..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeArgsBinding.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; - -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.asm.location.Location.InvokeLocation; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * invoke 传入的参数列表,有严格的限制,只能在 invoke 之前。 - * - * TODO ,当 static 函数时,在数组前,传一个null进去? 不然,不好区分是否 static 函数调用?? - * - * @author hengyunabc - * - */ -public class InvokeArgsBinding extends Binding { - - @Override - public boolean fromStack() { - return true; - } - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - Location location = bindingContext.getLocation(); - - if(location instanceof InvokeLocation) { - InvokeLocation invokeLocation = (InvokeLocation) location; - if(invokeLocation.isWhenComplete()) { - throw new IllegalArgumentException("InvokeArgsBinding can not work on InvokeLocation whenComplete is true."); - } - }else { - throw new IllegalArgumentException("current location is not invoke location. location: " + location); - } - - LocalVariableNode invokeArgsVariableNode = bindingContext.getMethodProcessor().initInvokeArgsVariableNode(); - AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index); - } - - @Override - public Type getType(BindingContext bindingContext) { - return AsmOpUtils.OBJECT_ARRAY_TYPE; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeInfoBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeInfoBinding.java deleted file mode 100644 index 36e550160..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeInfoBinding.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LineNumberNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.taobao.arthas.bytekit.asm.location.MethodInsnNodeWare; -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * 包含 owner/method name/ method desc/ line number - * - * @author hengyunabc 2020-05-14 - * - */ -public class InvokeInfoBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - Location location = bindingContext.getLocation(); - if (location instanceof MethodInsnNodeWare) { - MethodInsnNodeWare methodInsnNodeWare = (MethodInsnNodeWare) location; - MethodInsnNode methodInsnNode = methodInsnNodeWare.methodInsnNode(); - - int line = -1; - - if (location.isWhenComplete() == false) { - AbstractInsnNode insnNode = methodInsnNode.getPrevious(); - while (insnNode != null) { - if (insnNode instanceof LineNumberNode) { - line = ((LineNumberNode) insnNode).line; - break; - } - insnNode = insnNode.getPrevious(); - } - } else { - AbstractInsnNode insnNode = methodInsnNode.getNext(); - while (insnNode != null) { - if (insnNode instanceof LineNumberNode) { - line = ((LineNumberNode) insnNode).line; - break; - } - insnNode = insnNode.getNext(); - } - } - - String result = methodInsnNode.owner + "|" + methodInsnNode.name + "|" + methodInsnNode.desc + "|" + line; - AsmOpUtils.push(instructions, result); - - } else { - throw new IllegalArgumentException( - "InvokeMethodNameBinding location is not Invocation location, location: " + location); - } - - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(String.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodDeclarationBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodDeclarationBinding.java deleted file mode 100644 index 2c802068a..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodDeclarationBinding.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.taobao.arthas.bytekit.asm.location.MethodInsnNodeWare; -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * - * @author hengyunabc - * - */ -public class InvokeMethodDeclarationBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - Location location = bindingContext.getLocation(); - if (location instanceof MethodInsnNodeWare) { - MethodInsnNodeWare methodInsnNodeWare = (MethodInsnNodeWare) location; - MethodInsnNode methodInsnNode = methodInsnNodeWare.methodInsnNode(); - AsmOpUtils.push(instructions, methodInsnNode.desc); - - } else { - throw new IllegalArgumentException( - "InvokeMethodDeclarationBinding location is not Invocation location, location: " + location); - } - - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(String.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodNameBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodNameBinding.java deleted file mode 100644 index 581bb0646..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodNameBinding.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.taobao.arthas.bytekit.asm.location.MethodInsnNodeWare; -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * - * @author hengyunabc - * - */ -public class InvokeMethodNameBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - Location location = bindingContext.getLocation(); - if (location instanceof MethodInsnNodeWare) { - MethodInsnNodeWare methodInsnNodeWare = (MethodInsnNodeWare) location; - MethodInsnNode methodInsnNode = methodInsnNodeWare.methodInsnNode(); - AsmOpUtils.push(instructions, methodInsnNode.name); - - } else { - throw new IllegalArgumentException( - "InvokeMethodNameBinding location is not Invocation location, location: " + location); - } - - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(String.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodOwnerBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodOwnerBinding.java deleted file mode 100644 index 9a962d4bc..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeMethodOwnerBinding.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.taobao.arthas.bytekit.asm.location.MethodInsnNodeWare; -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * - * @author hengyunabc 2020-05-02 - * - */ -public class InvokeMethodOwnerBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - Location location = bindingContext.getLocation(); - if (location instanceof MethodInsnNodeWare) { - MethodInsnNodeWare methodInsnNodeWare = (MethodInsnNodeWare) location; - MethodInsnNode methodInsnNode = methodInsnNodeWare.methodInsnNode(); - AsmOpUtils.push(instructions, methodInsnNode.owner); - - } else { - throw new IllegalArgumentException( - "InvokeMethodOwnerBinding location is not Invocation location, location: " + location); - } - - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(String.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeReturnBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeReturnBinding.java deleted file mode 100644 index d36d786c5..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/InvokeReturnBinding.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; - -/** - * invoke 的返回值 - * @author hengyunabc - * - */ -public class InvokeReturnBinding extends Binding { - - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode(); - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - String uniqueNameForMethod = AsmUtils.uniqueNameForMethod(methodInsnNode.owner, methodInsnNode.name, - methodInsnNode.desc); - Type invokeReturnType = Type.getMethodType(methodInsnNode.desc).getReturnType(); - if(invokeReturnType.equals(Type.VOID_TYPE)) { - AsmOpUtils.push(instructions, null); - }else { - LocalVariableNode invokeReturnVariableNode = methodProcessor.initInvokeReturnVariableNode( - uniqueNameForMethod, Type.getMethodType(methodInsnNode.desc).getReturnType()); - AsmOpUtils.loadVar(instructions, invokeReturnType, invokeReturnVariableNode.index); - } - } else { - throw new IllegalArgumentException( - "InvokeReturnBinding location is not MethodInsnNode, insnNode: " + insnNode); - } - - } - - @Override - public boolean fromStack() { - return true; - } - - @Override - public Type getType(BindingContext bindingContext) { - AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode(); - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - Type invokeReturnType = Type.getMethodType(methodInsnNode.desc).getReturnType(); - return invokeReturnType; - } else { - throw new IllegalArgumentException( - "InvokeReturnBinding location is not MethodInsnNode, insnNode: " + insnNode); - } - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LineBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LineBinding.java deleted file mode 100644 index 7c1e80073..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LineBinding.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LineNumberNode; - -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * - * @author hengyunabc - * - */ -public class LineBinding extends Binding { - - private boolean exact; - - public LineBinding(boolean exact) { - this.exact = exact; - } - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - Location location = bindingContext.getLocation(); - AbstractInsnNode insnNode = location.getInsnNode(); - - int line = -1; - if (exact) { - if (insnNode instanceof LineNumberNode) { - line = ((LineNumberNode) insnNode).line; - } else { - throw new IllegalArgumentException("LineBinding location is not LineNumberNode, insnNode: " + insnNode); - } - } else { - if (location.isWhenComplete() == false) { - while (insnNode != null) { - if (insnNode instanceof LineNumberNode) { - line = ((LineNumberNode) insnNode).line; - break; - } - insnNode = insnNode.getPrevious(); - } - } else { - while (insnNode != null) { - if (insnNode instanceof LineNumberNode) { - line = ((LineNumberNode) insnNode).line; - break; - } - insnNode = insnNode.getNext(); - } - } - } - AsmOpUtils.push(instructions, line); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(int.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LocalVarNamesBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LocalVarNamesBinding.java deleted file mode 100644 index 56bffb23e..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LocalVarNamesBinding.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; - -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -public class LocalVarNamesBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - AbstractInsnNode currentInsnNode = bindingContext.getLocation().getInsnNode(); - List results = AsmOpUtils - .validVariables(bindingContext.getMethodProcessor().getMethodNode().localVariables, currentInsnNode); - - AsmOpUtils.push(instructions, results.size()); - AsmOpUtils.newArray(instructions, AsmOpUtils.STRING_TYPE); - - for (int i = 0; i < results.size(); ++i) { - AsmOpUtils.dup(instructions); - - AsmOpUtils.push(instructions, i); - AsmOpUtils.push(instructions, results.get(i).name); - - AsmOpUtils.arrayStore(instructions, AsmOpUtils.STRING_TYPE); - } - } - - @Override - public Type getType(BindingContext bindingContext) { - return AsmOpUtils.STRING_ARRAY_TYPE; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LocalVarsBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LocalVarsBinding.java deleted file mode 100644 index 7f1ccac86..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/LocalVarsBinding.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; - -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * TODO 增加一个配置,是否包含 method args - * @author hengyunabc - * - */ -public class LocalVarsBinding extends Binding{ - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - - AbstractInsnNode currentInsnNode = bindingContext.getLocation().getInsnNode(); - - List results = AsmOpUtils - .validVariables(bindingContext.getMethodProcessor().getMethodNode().localVariables, currentInsnNode); - - AsmOpUtils.push(instructions, results.size()); - AsmOpUtils.newArray(instructions, AsmOpUtils.OBJECT_TYPE); - - for (int i = 0; i < results.size(); ++i) { - AsmOpUtils.dup(instructions); - - AsmOpUtils.push(instructions, i); - - LocalVariableNode variableNode = results.get(i); - AsmOpUtils.loadVar(instructions, Type.getType(variableNode.desc), variableNode.index); - AsmOpUtils.box(instructions, Type.getType(variableNode.desc)); - - AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE); - } - - } - - @Override - public Type getType(BindingContext bindingContext) { - return AsmOpUtils.OBJECT_ARRAY_TYPE; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodBinding.java deleted file mode 100644 index d3ba3c785..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodBinding.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * @author hengyunabc - * - */ -public class MethodBinding extends Binding{ - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - // 先获取类本身的 class ,再调用 getDeclaredMethod ,它需要一个变长参数,实际上要传一个数组 - /** - * @see java.lang.Class.getDeclaredMethod(String, Class...) - */ - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - AsmOpUtils.ldc(instructions, Type.getObjectType(methodProcessor.getOwner())); - - AsmOpUtils.push(instructions, methodProcessor.getMethodNode().name); - - Type[] argumentTypes = Type.getMethodType(methodProcessor.getMethodNode().desc).getArgumentTypes(); - - AsmOpUtils.push(instructions, argumentTypes.length); - AsmOpUtils.newArray(instructions, Type.getType(Class.class)); - - for(int i = 0; i < argumentTypes.length; ++i) { - AsmOpUtils.dup(instructions); - - AsmOpUtils.push(instructions, i); - - AsmOpUtils.ldc(instructions, argumentTypes[i]); - AsmOpUtils.arrayStore(instructions, Type.getType(Class.class)); - } - - MethodInsnNode declaredMethodInsnNode = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Type.getType(Class.class).getInternalName(), - "getDeclaredMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - instructions.add(declaredMethodInsnNode); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(java.lang.reflect.Method.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodDeclarationBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodDeclarationBinding.java deleted file mode 100644 index bd9d442e3..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodDeclarationBinding.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * TODO 提供一个完整的 method 的string,包含类名,并不是desc?用户可以自己提取descs method的定义,前面是 public - * /static 这些关键字,是有限的几个。后面是 throws ,的异常信息。 或者做一下取巧比如把 classname | methoname | desc 之类连起一个String - * - * @author hengyunabc - * - */ -public class MethodDeclarationBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); -// AsmOpUtils.ldc(instructions, AsmUtils.methodDeclaration(Type.getObjectType(methodProcessor.getOwner()), -// methodProcessor.getMethodNode())); - AsmOpUtils.ldc(instructions, methodProcessor.getMethodNode().desc); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(String.class); - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodInfoBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodInfoBinding.java deleted file mode 100644 index 849bf661f..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodInfoBinding.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * method name | method desc 的方式组织 - * - * TODO 是否要有 line number ? - * - * @author hengyunabc 2020-05-16 - * - */ -public class MethodInfoBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - MethodNode methodNode = methodProcessor.getMethodNode(); - AsmOpUtils.ldc(instructions, methodNode.name + '|' + methodNode.desc); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(String.class); - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodNameBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodNameBinding.java deleted file mode 100644 index 148d5178f..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MethodNameBinding.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -/** - * @author hengyunabc - * - */ -public class MethodNameBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - AsmOpUtils.ldc(instructions, methodProcessor.getMethodNode().name); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(String.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MonitorBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MonitorBinding.java deleted file mode 100644 index 8dcffb6e8..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/MonitorBinding.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; - -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.asm.location.Location.SyncEnterLocation; -import com.taobao.arthas.bytekit.asm.location.Location.SyncExitLocation; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -public class MonitorBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - Location location = bindingContext.getLocation(); - - if (location.isWhenComplete()) { - throw new IllegalArgumentException("MonitorBinding only support location whenComplete is false."); - } - - if (location instanceof SyncEnterLocation || location instanceof SyncExitLocation) { - LocalVariableNode monitorVariableNode = bindingContext.getMethodProcessor().initMonitorVariableNode(); - AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_TYPE, monitorVariableNode.index); - } else { - throw new IllegalArgumentException( - "MonitorBinding only support SyncEnterLocation or SyncExitLocation. location: " + location); - } - } - - @Override - public boolean fromStack() { - return true; - } - - @Override - public Type getType(BindingContext bindingContext) { - return AsmOpUtils.OBJECT_TYPE; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ReturnBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ReturnBinding.java deleted file mode 100644 index 66c959ba5..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ReturnBinding.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; - -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; - -public class ReturnBinding extends Binding { - - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - //check location - - Location location = bindingContext.getLocation(); - - if (!AsmOpUtils.isReturnCode(location.getInsnNode().getOpcode())) { - throw new IllegalArgumentException("current location is not return location. location: " + location); - } - - Type returnType = bindingContext.getMethodProcessor().getReturnType(); - if(returnType.equals(Type.VOID_TYPE)) { - AsmOpUtils.push(instructions, null); - }else { - LocalVariableNode returnVariableNode = bindingContext.getMethodProcessor().initReturnVariableNode(); - AsmOpUtils.loadVar(instructions, returnType, returnVariableNode.index); - } - - } - - @Override - public boolean fromStack() { - return true; - } - - @Override - public Type getType(BindingContext bindingContext) { - return bindingContext.getMethodProcessor().getReturnType(); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/StackSaver.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/StackSaver.java deleted file mode 100644 index 2f5b22aa1..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/StackSaver.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -/** - * 在 return/throw/invoke 等location时,需要把栈上的值保存到locals里 - * @author hengyunabc - * - */ -public interface StackSaver { - /** - * 有可能在两个地方被调用。1: 在最开始保存栈上的值时, 2: callback函数有返回值,想更新这个值时。stackSaver自己内部要保证保存的locals index是一致的 - * @param instructions - * @param bindingContext - */ - public void store(InsnList instructions, BindingContext bindingContext); - - public void load(InsnList instructions, BindingContext bindingContext); - - public Type getType(BindingContext bindingContext); - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ThisBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ThisBinding.java deleted file mode 100644 index 1e90140a4..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ThisBinding.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -public class ThisBinding extends Binding { - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - bindingContext.getMethodProcessor().loadThis(instructions); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(Object.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ThrowableBinding.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ThrowableBinding.java deleted file mode 100644 index f05f5399d..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/ThrowableBinding.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; - -/** - * TODO 要检查 location 是否是合法的 - * @author hengyunabc - * - */ -public class ThrowableBinding extends Binding { - - @Override - public boolean fromStack() { - return true; - } - - @Override - public void pushOntoStack(InsnList instructions, BindingContext bindingContext) { - // TODO 这里从 StackSaver 里取是否合理? - bindingContext.getStackSaver().load(instructions, bindingContext); - // 是否要 check cast ? - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(Throwable.class); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/annotation/BindingParser.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/annotation/BindingParser.java deleted file mode 100644 index c507e3846..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/annotation/BindingParser.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding.annotation; - -import java.lang.annotation.Annotation; - -import com.taobao.arthas.bytekit.asm.binding.Binding; - -public interface BindingParser { - - public Binding parse(Annotation annotation); - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/annotation/BindingParserHandler.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/annotation/BindingParserHandler.java deleted file mode 100644 index b898f6002..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/binding/annotation/BindingParserHandler.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.taobao.arthas.bytekit.asm.binding.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.ANNOTATION_TYPE) -public @interface BindingParserHandler { - - Class parser(); - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/Instrument.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/Instrument.java deleted file mode 100644 index 1dc51dba6..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/Instrument.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - - -/** - * 在这里支持配置一个 error hander ?做为插入的异常处理的 - * - * 按名字匹配,按模糊匹配??有没有这样子的需求?,按interface匹配,按基础类继承的匹配 - * - * 函数的匹配,直接是名字一样,desc 一样的。 匹配有 annotation 的 - * - * 只有 NewField 才是加新的field,原来类里有的field,就直接写上就可以了。 - * @author hengyunabc - * - */ -@Target({ java.lang.annotation.ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -public @interface Instrument { -// Instrumentation -// MatchType type() default MatchType.ExactClass; - - String[] Class() default {}; - String[] BaseClass() default {}; - String[] Interface() default {}; - - String originalName() default ""; - - Class suppress() default Throwable.class; - - Class suppressHandler() default Void.class; -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/InstrumentApi.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/InstrumentApi.java deleted file mode 100644 index d9e48a5db..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/InstrumentApi.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - - -/** - * - *
- * 实现这个 invokeOrigin(),需要多步处理:
- *
- * 传入要被替换的类,读取到标记了 @Instrument 的类。 类名不一样的话,先替换类名?
- *
- * 然后查找所有的 field,如果有标记了 @NewField ,则增加到要被替换的类里。
- *
- * 然后查找所有的函数, 再查找是否在 旧类里有同样签名的,如果有,则执行清除行号, 替换 invokeOrigin() ,再 inline 原来的旧函数
- *
- * 再替换函数到 旧类里。
- *
- * 类名有可能要替换
- *
- * 
- * - * - * - * - * - * @author hengyunabc 2019-02-25 - * - */ -public class InstrumentApi { - public static final T invokeOrigin() { - return null; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/NewField.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/NewField.java deleted file mode 100644 index 3e0707a04..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/NewField.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ java.lang.annotation.ElementType.FIELD }) -@Retention(RetentionPolicy.RUNTIME) -public @interface NewField { -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/impl/InstrumentImpl.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/impl/InstrumentImpl.java deleted file mode 100644 index 977a42050..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/impl/InstrumentImpl.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst.impl; - -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.commons.Method; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.TypeInsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; - -/** - * - * @author hengyunabc 2019-03-15 - * - */ -public class InstrumentImpl { - - public static MethodNode replaceInvokeOrigin(String originOwner, MethodNode originMethodNode, - MethodNode apmMethodNode) { - - // 查找到所有的 InstrumentApi.invokeOrigin() 指令 - List methodInsnNodes = AsmUtils.findMethodInsnNode(apmMethodNode, - "com/taobao/arthas/bytekit/asm/inst/InstrumentApi", "invokeOrigin", "()Ljava/lang/Object;"); - - Type originReturnType = Type.getMethodType(originMethodNode.desc).getReturnType(); - - for (MethodInsnNode methodInsnNode : methodInsnNodes) { - InsnList instructions = new InsnList(); - - AbstractInsnNode secondInsnNode = methodInsnNode.getNext(); - - // 如果是 非 static ,则要 load this - boolean isStatic = AsmUtils.isStatic(originMethodNode); - int opcode = isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL; - if (!isStatic) { - AsmOpUtils.loadThis(instructions); - } - AsmOpUtils.loadArgs(instructions, originMethodNode); - - MethodInsnNode originMethodInsnNode = new MethodInsnNode(opcode, originOwner, originMethodNode.name, - originMethodNode.desc, false); - // 调用原来的函数 - instructions.add(originMethodInsnNode); - - int sort = originReturnType.getSort(); - if (sort == Type.VOID) { - if (secondInsnNode != null) { - if (secondInsnNode.getOpcode() == Opcodes.POP) { - // TODO 原来的函数没有返回值,这里要把 POP去掉。有没有可能是 POP2 ? - apmMethodNode.instructions.remove(secondInsnNode); - } else { - // TODO 原来函数没有返回值,这里有没有可能要赋值??是否要 push null? - AsmOpUtils.pushNUll(instructions); - } - } - } else if (sort >= Type.BOOLEAN && sort <= Type.DOUBLE) { - if (secondInsnNode.getOpcode() == Opcodes.POP) { - // 原来是 pop掉一个栈,如果函数返回的是 long,则要pop2 - if (originReturnType.getSize() == 2) { - apmMethodNode.instructions.insert(secondInsnNode, new InsnNode(Opcodes.POP2)); - apmMethodNode.instructions.remove(secondInsnNode); - } - } else { - /** - * 需要把下面两条cast和unbox的指令删掉 - * - *
-                     * CHECKCAST java/lang/Integer
-                     * INVOKEVIRTUAL java/lang/Integer.intValue ()I
-                     * 
- */ - boolean removeCheckCast = false; - if (secondInsnNode.getOpcode() == Opcodes.CHECKCAST) { - TypeInsnNode typeInsnNode = (TypeInsnNode) secondInsnNode; - // 从原始函数的返回值,获取到它对应的自动box的类 - Type boxedType = AsmOpUtils.getBoxedType(originReturnType); - if (Type.getObjectType(typeInsnNode.desc).equals(boxedType)) { - AbstractInsnNode thridInsnNode = secondInsnNode.getNext(); - if (thridInsnNode != null && thridInsnNode.getOpcode() == Opcodes.INVOKEVIRTUAL) { - MethodInsnNode valueInsnNode = (MethodInsnNode) thridInsnNode; - Method unBoxMethod = AsmOpUtils.getUnBoxMethod(originReturnType); - if (unBoxMethod.getDescriptor().equals(valueInsnNode.desc) - && valueInsnNode.owner.equals(boxedType.getInternalName())) { - apmMethodNode.instructions.remove(thridInsnNode); - apmMethodNode.instructions.remove(secondInsnNode); - removeCheckCast = true; - } - } - } - } - if (!removeCheckCast) { - // 没有被转换为原始类型,也没有pop,则说明赋值给了一个对象,用类似Long.valudOf转换为Object - AsmOpUtils.box(instructions, originReturnType); - - } - - } - } else {// ARRAY/OBJECT - // 移掉可能有的 check cast - if (secondInsnNode.getOpcode() == Opcodes.CHECKCAST) { - TypeInsnNode typeInsnNode = (TypeInsnNode) secondInsnNode; - if (Type.getObjectType(typeInsnNode.desc).equals(originReturnType)) { - apmMethodNode.instructions.remove(secondInsnNode); - } - } - } - apmMethodNode.instructions.insertBefore(methodInsnNode, instructions); - apmMethodNode.instructions.remove(methodInsnNode); - } - - MethodProcessor methodProcessor = new MethodProcessor(originOwner, apmMethodNode); - methodProcessor.inline(originOwner, originMethodNode); - - return apmMethodNode; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/impl/MethodReplaceResult.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/impl/MethodReplaceResult.java deleted file mode 100644 index b45d22eba..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/inst/impl/MethodReplaceResult.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst.impl; - -import com.alibaba.arthas.deps.org.objectweb.asm.Label; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; - -/** - * - * @author hengyunabc 2019-03-18 - * - */ -public class MethodReplaceResult { - - private boolean success; - - private Label start; - private Label end; - - private MethodNode methodNode; - - public Label getStart() { - return start; - } - - public void setStart(Label start) { - this.start = start; - } - - public Label getEnd() { - return end; - } - - public void setEnd(Label end) { - this.end = end; - } - - public MethodNode getMethodNode() { - return methodNode; - } - - public void setMethodNode(MethodNode methodNode) { - this.methodNode = methodNode; - } - - public boolean isSuccess() { - return success; - } - - public void setSuccess(boolean success) { - this.success = success; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/EnterInteceptor.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/EnterInteceptor.java deleted file mode 100644 index 5ff6fc0f6..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/EnterInteceptor.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -public class EnterInteceptor { - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/ExceptionInterceptor.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/ExceptionInterceptor.java deleted file mode 100644 index 9c44d2bf1..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/ExceptionInterceptor.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -public class ExceptionInterceptor { - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/ExitInterceptor.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/ExitInterceptor.java deleted file mode 100644 index 894cf1996..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/ExitInterceptor.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -public class ExitInterceptor { - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/Inteceptor.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/Inteceptor.java deleted file mode 100644 index ac690943b..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/Inteceptor.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -public interface Inteceptor { - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/InterceptorMethodConfig.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/InterceptorMethodConfig.java deleted file mode 100644 index 33fba23e0..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/InterceptorMethodConfig.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import java.util.List; - -import com.taobao.arthas.bytekit.asm.binding.Binding; - -public class InterceptorMethodConfig { - - private boolean inline; - - private String owner; - - private String methodName; - - private String methodDesc; - - private List bindings; - - /** - * 插入的代码用 try/catch 包围的异常类型 - */ - private String suppress; - - public boolean isInline() { - return inline; - } - - public void setInline(boolean inline) { - this.inline = inline; - } - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - - public String getMethodName() { - return methodName; - } - - public void setMethodName(String methodName) { - this.methodName = methodName; - } - - public String getMethodDesc() { - return methodDesc; - } - - public void setMethodDesc(String methodDesc) { - this.methodDesc = methodDesc; - } - - public List getBindings() { - return bindings; - } - - public void setBindings(List bindings) { - this.bindings = bindings; - } - - public String getSuppress() { - return suppress; - } - - public void setSuppress(String suppress) { - this.suppress = suppress; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/InterceptorProcessor.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/InterceptorProcessor.java deleted file mode 100644 index 739d9eb79..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/InterceptorProcessor.java +++ /dev/null @@ -1,255 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.JumpInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LabelNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.TryCatchBlock; -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.binding.BindingContext; -import com.taobao.arthas.bytekit.asm.binding.StackSaver; -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class InterceptorProcessor { - - private LocationMatcher locationMatcher; - - /** - * 插入的回调函数的配置 - */ - private InterceptorMethodConfig interceptorMethodConfig; - - /** - * 插入的代码被 try/catch 包围的配置,注意有一些location插入try/catch会可能失败,因为不能确切知道栈上的情况 - */ - private InterceptorMethodConfig exceptionHandlerConfig; - - /** - * 加载inlne类所需要的ClassLoader - */ - private ClassLoader classLoader; - - public InterceptorProcessor(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - public List process(MethodProcessor methodProcessor) throws Exception { - List locations = locationMatcher.match(methodProcessor); - - List interceptorBindings = interceptorMethodConfig.getBindings(); - - for (Location location : locations) { - - // 有三小段代码,1: 保存当前栈上的值的 , 2: 插入的回调的 , 3:恢复当前栈的 - - InsnList toInsert = new InsnList(); - - InsnList stackSaveInsnList = new InsnList(); - InsnList stackLoadInsnList = new InsnList(); - - StackSaver stackSaver = null; - if(location.isStackNeedSave()) { - stackSaver = location.getStackSaver(); - } - BindingContext bindingContext = new BindingContext(location, methodProcessor, stackSaver); - - if(stackSaver != null) { - stackSaver.store(stackSaveInsnList, bindingContext); - stackSaver.load(stackLoadInsnList, bindingContext); - } - - - Type methodType = Type.getMethodType(interceptorMethodConfig.getMethodDesc()); - Type[] argumentTypes = methodType.getArgumentTypes(); - // 检查回调函数的参数和 binding数一致 - if(interceptorBindings.size() != argumentTypes.length) { - throw new IllegalArgumentException("interceptorBindings size no equals with interceptorMethod args size."); - } - - // 把当前栈上的数据保存起来 - int fromStackBindingCount = 0; - for (Binding binding : interceptorBindings) { - if(binding.fromStack()) { - fromStackBindingCount++; - } - } - // 只允许一个binding从栈上保存数据 - if(fromStackBindingCount > 1) { - throw new IllegalArgumentException("interceptorBindings have more than one from stack Binding."); - } - - - // 组装好要调用的 static 函数的参数 - for(int i = 0 ; i < argumentTypes.length; ++i) { - Binding binding = interceptorBindings.get(i); - binding.pushOntoStack(toInsert, bindingContext); - // 检查 回调函数的参数类型,看是否要box一下 ,检查是否原始类型就可以了。 - // 只有类型不一样时,才需要判断。比如两个都是 long,则不用判断 - Type bindingType = binding.getType(bindingContext); - if(!bindingType.equals(argumentTypes[i])) { - if(AsmOpUtils.needBox(bindingType)) { - AsmOpUtils.box(toInsert, binding.getType(bindingContext)); - } - } - } - - // TODO 要检查 binding 和 回调的函数的参数类型是否一致。回调函数的类型可以是 Object,或者super。但是不允许一些明显的类型问题,比如array转到int - - toInsert.add(new MethodInsnNode(Opcodes.INVOKESTATIC, interceptorMethodConfig.getOwner(), interceptorMethodConfig.getMethodName(), - interceptorMethodConfig.getMethodDesc(), false)); - - if (!methodType.getReturnType().equals(Type.VOID_TYPE)) { - if (location.canChangeByReturn()) { - // 当回调函数有返回值时,需要更新到之前保存的栈上 - // TODO 这里应该有 type 的问题?需要检查是否要 box - Type returnType = methodType.getReturnType(); - Type stackSaverType = stackSaver.getType(bindingContext); - if (!returnType.equals(stackSaverType)) { - AsmOpUtils.unbox(toInsert, stackSaverType); - } - stackSaver.store(toInsert, bindingContext); - } else { - // 没有使用到回调函数的返回值的话,则需要从栈上清理掉 - int size = methodType.getReturnType().getSize(); - if (size == 1) { - AsmOpUtils.pop(toInsert); - } else if (size == 2) { - AsmOpUtils.pop2(toInsert); - } - } - } - - - TryCatchBlock errorHandlerTryCatchBlock = null; - // 生成的代码用try/catch包围起来 - if( exceptionHandlerConfig != null) { - LabelNode gotoDest = new LabelNode(); - - errorHandlerTryCatchBlock = new TryCatchBlock(methodProcessor.getMethodNode(), exceptionHandlerConfig.getSuppress()); - toInsert.insertBefore(toInsert.getFirst(), errorHandlerTryCatchBlock.getStartLabelNode()); - toInsert.add(new JumpInsnNode(Opcodes.GOTO, gotoDest)); - toInsert.add(errorHandlerTryCatchBlock.getEndLabelNode()); -// 这里怎么把栈上的数据保存起来?还是强制回调函数的第一个参数是 exception,后面的binding可以随便搞。 - -// MethodInsnNode printStackTrace = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "printStackTrace", "()V", false); -// toInsert.add(printStackTrace); - - errorHandler(methodProcessor, toInsert); - - toInsert.add(gotoDest); - } - -// System.err.println(Decompiler.toString(toInsert)); - - - stackSaveInsnList.add(toInsert); - stackSaveInsnList.add(stackLoadInsnList); - if (location.isWhenComplete()) { - methodProcessor.getMethodNode().instructions.insert(location.getInsnNode(), stackSaveInsnList); - }else { - methodProcessor.getMethodNode().instructions.insertBefore(location.getInsnNode(), stackSaveInsnList); - } - - if( exceptionHandlerConfig != null) { - errorHandlerTryCatchBlock.sort(); - } - - // inline callback - if(interceptorMethodConfig.isInline()) { -// Class forName = Class.forName(Type.getObjectType(interceptorMethodConfig.getOwner()).getClassName()); - - Class forName = classLoader.loadClass(Type.getObjectType(interceptorMethodConfig.getOwner()).getClassName()); - MethodNode toInlineMethodNode = AsmUtils.findMethod(AsmUtils.loadClass(forName).methods, interceptorMethodConfig.getMethodName(), interceptorMethodConfig.getMethodDesc()); - - methodProcessor.inline(interceptorMethodConfig.getOwner(), toInlineMethodNode); - } - if(exceptionHandlerConfig != null && exceptionHandlerConfig.isInline()) { -// Class forName = Class.forName(Type.getObjectType(exceptionHandlerConfig.getOwner()).getClassName()); - - Class forName = classLoader.loadClass(Type.getObjectType(exceptionHandlerConfig.getOwner()).getClassName()); - MethodNode toInlineMethodNode = AsmUtils.findMethod(AsmUtils.loadClass(forName).methods, exceptionHandlerConfig.getMethodName(), exceptionHandlerConfig.getMethodDesc()); - - methodProcessor.inline(exceptionHandlerConfig.getOwner(), toInlineMethodNode); - } - -// System.err.println(Decompiler.toString(methodProcessor.getMethodNode())); -// System.err.println(AsmUtils.toASMCode(methodProcessor.getMethodNode())); - } - - return locations; - } - - private void errorHandler(MethodProcessor methodProcessor, InsnList insnList) { -// MethodInsnNode printStackTrace = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "printStackTrace", "()V", false); -// insnList.add(printStackTrace); - // 第一个参数要求是 throwable ,或者一个exception ? - // 有很多 binding 并不能使用的,因为location不生效 - BindingContext bindingContext = new BindingContext(null, methodProcessor, null); - Type methodType = Type.getMethodType(this.exceptionHandlerConfig.getMethodDesc()); - Type[] argumentTypes = methodType.getArgumentTypes(); - List bindings = this.exceptionHandlerConfig.getBindings(); - if(bindings.size() + 1 != argumentTypes.length) { - throw new IllegalArgumentException("errorHandler bindings size do not match error method args size."); - } - if(!argumentTypes[0].equals(Type.getType(Throwable.class))) { - throw new IllegalArgumentException("errorHandler method first arg type must be Throwable."); - } - // 组装好要调用的 static 函数的参数 - for(Binding binding: bindings) { - if(binding.fromStack()) { - throw new IllegalArgumentException("errorHandler binding can not load value from stack!"); - } - binding.pushOntoStack(insnList, bindingContext); - // 检查 回调函数的参数类型,看是否要box一下 ,检查是否原始类型就可以了。 - if(AsmOpUtils.needBox(binding.getType(bindingContext))) { - AsmOpUtils.box(insnList, binding.getType(bindingContext)); - } - } - - insnList.add(new MethodInsnNode(Opcodes.INVOKESTATIC, exceptionHandlerConfig.getOwner(), exceptionHandlerConfig.getMethodName(), - exceptionHandlerConfig.getMethodDesc(), false)); - - int size = methodType.getReturnType().getSize(); - if (size == 1) { - AsmOpUtils.pop(insnList); - } else if (size == 2) { - AsmOpUtils.pop2(insnList); - } - } - - public LocationMatcher getLocationMatcher() { - return locationMatcher; - } - - public void setLocationMatcher(LocationMatcher locationMatcher) { - this.locationMatcher = locationMatcher; - } - - public InterceptorMethodConfig getInterceptorMethodConfig() { - return interceptorMethodConfig; - } - - public void setInterceptorMethodConfig(InterceptorMethodConfig interceptorMethodConfig) { - this.interceptorMethodConfig = interceptorMethodConfig; - } - - public InterceptorMethodConfig getExceptionHandlerConfig() { - return exceptionHandlerConfig; - } - - public void setExceptionHandlerConfig(InterceptorMethodConfig exceptionHandlerConfig) { - this.exceptionHandlerConfig = exceptionHandlerConfig; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtEnter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtEnter.java deleted file mode 100644 index 4374faee2..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtEnter.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtEnter.EnterInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.EnterLocationMatcher; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = EnterInterceptorProcessorParser.class) -public @interface AtEnter { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - class EnterInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - LocationMatcher locationMatcher = new EnterLocationMatcher(); - - AtEnter atEnter = (AtEnter) annotationOnMethod; - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atEnter.inline(), - atEnter.suppress(), - atEnter.suppressHandler()); - - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtExceptionExit.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtExceptionExit.java deleted file mode 100644 index aaa746277..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtExceptionExit.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExceptionExit.ExceptionExitInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.ExceptionExitLocationMatcher; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = ExceptionExitInterceptorProcessorParser.class) -public @interface AtExceptionExit { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - Class onException() default Throwable.class; - - class ExceptionExitInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtExceptionExit atExceptionExit = (AtExceptionExit) annotationOnMethod; - - LocationMatcher locationMatcher = new ExceptionExitLocationMatcher(Type.getInternalName(atExceptionExit.onException()));; - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atExceptionExit.inline(), - atExceptionExit.suppress(), - atExceptionExit.suppressHandler()); - - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtExit.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtExit.java deleted file mode 100644 index 94280ff0d..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtExit.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExit.ExitInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.ExitLocationMatcher; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = ExitInterceptorProcessorParser.class) -public @interface AtExit { - boolean inline() default true; - Class suppress() default None.class; - Class suppressHandler() default Void.class; - - class ExitInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtExit atExit = (AtExit) annotationOnMethod; - - LocationMatcher locationMatcher = new ExitLocationMatcher(); - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atExit.inline(), - atExit.suppress(), - atExit.suppressHandler()); - - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtFieldAccess.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtFieldAccess.java deleted file mode 100644 index aace229b1..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtFieldAccess.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtFieldAccess.FieldAccessInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.FieldAccessLocationMatcher; -import com.taobao.arthas.bytekit.asm.location.Location; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = FieldAccessInterceptorProcessorParser.class) -public @interface AtFieldAccess { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - java.lang.Class owner() default Void.class; - - java.lang.Class type() default Void.class; - - String name(); - - int count() default -1; - - int flags() default Location.ACCESS_READ | Location.ACCESS_WRITE; - - boolean whenComplete() default false; - - class FieldAccessInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtFieldAccess atFieldAccess = (AtFieldAccess) annotationOnMethod; - - String ownerClass = null; - String fieldDesc = null; - if(! atFieldAccess.owner().equals(Void.class)) { - ownerClass = Type.getType(atFieldAccess.owner()).getInternalName(); - } - if(!atFieldAccess.type().equals(Void.class)) { - fieldDesc = Type.getType(atFieldAccess.type()).getDescriptor(); - } - - LocationMatcher locationMatcher = new FieldAccessLocationMatcher( - ownerClass, - fieldDesc, atFieldAccess.name(), atFieldAccess.count(), - atFieldAccess.flags(), atFieldAccess.whenComplete()); - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atFieldAccess.inline(), - atFieldAccess.suppress(), - atFieldAccess.suppressHandler()); - - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtInvoke.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtInvoke.java deleted file mode 100644 index ff76e8e0c..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtInvoke.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtInvoke.InvokeInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.InvokeLocationMatcher; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = InvokeInterceptorProcessorParser.class) -public @interface AtInvoke { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - Class owner() default Void.class; - - String name(); - - String desc() default ""; - - int count() default -1; - - boolean whenComplete() default false; - - /** - * method name excludes - * @return - */ - String[] excludes() default {}; - - class InvokeInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtInvoke atInvoke = (AtInvoke) annotationOnMethod; - - String owner = null; - String desc = null; - if (!atInvoke.owner().equals(Void.class)) { - owner = Type.getType(atInvoke.owner()).getInternalName(); - } - if (atInvoke.desc().isEmpty()) { - desc = null; - } - - List excludes = new ArrayList(); - for (String exclude : atInvoke.excludes()) { - excludes.add(exclude); - } - - LocationMatcher locationMatcher = new InvokeLocationMatcher(owner, atInvoke.name(), desc, atInvoke.count(), - atInvoke.whenComplete(), excludes); - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atInvoke.inline(), - atInvoke.suppress(), - atInvoke.suppressHandler()); - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtInvokeException.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtInvokeException.java deleted file mode 100644 index a12de47f9..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtInvokeException.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtInvokeException.InvokeExceptionInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.InvokeLocationMatcher; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; - -/** - * - * @author hengyunabc 2020-05-03 - * - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = InvokeExceptionInterceptorProcessorParser.class) -public @interface AtInvokeException { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - Class owner() default Void.class; - - /** - * method name - * - * @return - */ - String name(); - - String desc() default ""; - - int count() default -1; - - String[] excludes() default {}; - - class InvokeExceptionInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtInvokeException atInvokeException = (AtInvokeException) annotationOnMethod; - - String owner = null; - String desc = null; - if (!atInvokeException.owner().equals(Void.class)) { - owner = Type.getType(atInvokeException.owner()).getInternalName(); - } - if (atInvokeException.desc().isEmpty()) { - desc = null; - } - - List excludes = new ArrayList(); - for (String exclude : atInvokeException.excludes()) { - excludes.add(exclude); - } - - LocationMatcher locationMatcher = new InvokeLocationMatcher(owner, atInvokeException.name(), desc, - atInvokeException.count(), true, excludes, true); - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atInvokeException.inline(), - atInvokeException.suppress(), - atInvokeException.suppressHandler()); - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtLine.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtLine.java deleted file mode 100644 index 3a6f6e6ad..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtLine.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtLine.LineInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.LineLocationMatcher; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = LineInterceptorProcessorParser.class) -public @interface AtLine { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - int[] lines(); - - class LineInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtLine atLine = (AtLine) annotationOnMethod; - - LocationMatcher locationMatcher = new LineLocationMatcher(atLine.lines()); - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atLine.inline(), - atLine.suppress(), - atLine.suppressHandler()); - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtSyncEnter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtSyncEnter.java deleted file mode 100644 index 07581a4dc..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtSyncEnter.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtSyncEnter.SyncEnterInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; -import com.taobao.arthas.bytekit.asm.location.SyncLocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = SyncEnterInterceptorProcessorParser.class) -public @interface AtSyncEnter { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - int count() default -1; - boolean whenComplete() default false; - - class SyncEnterInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtSyncEnter atSyncEnter = (AtSyncEnter) annotationOnMethod; - - LocationMatcher locationMatcher = new SyncLocationMatcher(Opcodes.MONITORENTER, atSyncEnter.count(), atSyncEnter.whenComplete()); - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atSyncEnter.inline(), - atSyncEnter.suppress(), - atSyncEnter.suppressHandler()); - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtSyncExit.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtSyncExit.java deleted file mode 100644 index 2411eceb6..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtSyncExit.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtSyncExit.SyncExitInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; -import com.taobao.arthas.bytekit.asm.location.SyncLocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = SyncExitInterceptorProcessorParser.class) -public @interface AtSyncExit { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - int count() default -1; - boolean whenComplete() default false; - - class SyncExitInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtSyncExit atSyncExit = (AtSyncExit) annotationOnMethod; - - LocationMatcher locationMatcher = new SyncLocationMatcher(Opcodes.MONITOREXIT, atSyncExit.count(), atSyncExit.whenComplete()); - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atSyncExit.inline(), - atSyncExit.suppress(), - atSyncExit.suppressHandler()); - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtThrow.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtThrow.java deleted file mode 100644 index 859525554..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/AtThrow.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtThrow.ThrowInterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; -import com.taobao.arthas.bytekit.asm.location.ThrowLocationMatcher; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -@InterceptorParserHander(parserHander = ThrowInterceptorProcessorParser.class) -public @interface AtThrow { - boolean inline() default true; - - Class suppress() default None.class; - - Class suppressHandler() default Void.class; - - int count() default -1; - - class ThrowInterceptorProcessorParser implements InterceptorProcessorParser { - - @Override - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod) { - - AtThrow atThrow = (AtThrow) annotationOnMethod; - - LocationMatcher locationMatcher = new ThrowLocationMatcher(atThrow.count()); - - return InterceptorParserUtils.createInterceptorProcessor(method, - locationMatcher, - atThrow.inline(), - atThrow.suppress(), - atThrow.suppressHandler()); - } - - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/BindingParserUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/BindingParserUtils.java deleted file mode 100644 index 5228c3014..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/BindingParserUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.binding.annotation.BindingParser; -import com.taobao.arthas.bytekit.asm.binding.annotation.BindingParserHandler; -import com.taobao.arthas.bytekit.utils.InstanceUtils; - -public class BindingParserUtils { - - public static List parseBindings(Method method) { - // 从 parameter 里解析出来 binding - List bindings = new ArrayList(); - Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - for (int parameterIndex = 0; parameterIndex < parameterAnnotations.length; ++parameterIndex) { - Annotation[] annotationsOnParameter = parameterAnnotations[parameterIndex]; - for (int j = 0; j < annotationsOnParameter.length; ++j) { - - Annotation[] annotationsOnBinding = annotationsOnParameter[j].annotationType().getAnnotations(); - for (Annotation annotationOnBinding : annotationsOnBinding) { - if (BindingParserHandler.class.isAssignableFrom(annotationOnBinding.annotationType())) { - BindingParserHandler bindingParserHandler = (BindingParserHandler) annotationOnBinding; - BindingParser bindingParser = InstanceUtils.newInstance(bindingParserHandler.parser()); - Binding binding = bindingParser.parse(annotationsOnParameter[j]); - bindings.add(binding); - } - } - } - } - return bindings; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/EmptySuppressHandler.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/EmptySuppressHandler.java deleted file mode 100644 index 4568199d9..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/EmptySuppressHandler.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -public class EmptySuppressHandler { - - @ExceptionHandler - public static void onSuppress() { - - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/ExceptionHandler.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/ExceptionHandler.java deleted file mode 100644 index 384906832..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/ExceptionHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.METHOD) -public @interface ExceptionHandler { - boolean inline() default true; -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/ExceptionHandlerUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/ExceptionHandlerUtils.java deleted file mode 100644 index 65bfce33b..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/ExceptionHandlerUtils.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.binding.ThrowableBinding; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorMethodConfig; -import com.taobao.arthas.bytekit.utils.AnnotationUtils; -import com.taobao.arthas.bytekit.utils.ReflectionUtils; -import com.taobao.arthas.bytekit.utils.ReflectionUtils.MethodCallback; -import com.taobao.arthas.bytekit.utils.ReflectionUtils.MethodFilter; - -public class ExceptionHandlerUtils { - - public static InterceptorMethodConfig errorHandlerMethodConfig(Class suppress, Class handlerClass) { - - // TODO 要解析 errorHander Class里的内容 - final InterceptorMethodConfig errorHandlerMethodConfig = new InterceptorMethodConfig(); - - if(suppress.equals(None.class)) { - suppress = Throwable.class; - } - errorHandlerMethodConfig.setSuppress(Type.getType(suppress).getInternalName()); - - if (!handlerClass.equals(Void.class)) { - // find method with @ExceptionHandler - ReflectionUtils.doWithMethods(handlerClass, new MethodCallback() { - - @Override - public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - for (Annotation onMethodAnnotation : method.getAnnotations()) { - if (ExceptionHandler.class.isAssignableFrom(onMethodAnnotation.annotationType())) { - - if (!Modifier.isStatic(method.getModifiers())) { - throw new IllegalArgumentException("method must be static. method: " + method); - } - - ExceptionHandler handler = (ExceptionHandler) onMethodAnnotation; - - errorHandlerMethodConfig.setInline(handler.inline()); - - List errorHandlerBindings = BindingParserUtils.parseBindings(method); - // 检查第一个 bidning要是 Throwable Binding - if (errorHandlerBindings.size() == 0) { - throw new IllegalArgumentException( - "error handler bingins must have at least a binding"); - } - if (!(errorHandlerBindings.get(0) instanceof ThrowableBinding)) { - throw new IllegalArgumentException( - "error handler bingins first binding must be ThrowableBinding."); - } - // 去掉第一个 ThrowableBinding - // TODO 可能要copy一下,保证可以修改成功 - errorHandlerBindings.remove(0); - errorHandlerMethodConfig.setBindings(errorHandlerBindings); - errorHandlerMethodConfig.setOwner(Type.getInternalName(method.getDeclaringClass())); - errorHandlerMethodConfig.setMethodName(method.getName()); - errorHandlerMethodConfig.setMethodDesc(Type.getMethodDescriptor(method)); - } - } - - } - - }, new MethodFilter() { - - @Override - public boolean matches(Method method) { - return AnnotationUtils.findAnnotation(method, ExceptionHandler.class) != null; - } - - }); - } - - if (errorHandlerMethodConfig.getMethodDesc() == null) { - return null; - } - - return errorHandlerMethodConfig; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/InterceptorParserHander.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/InterceptorParserHander.java deleted file mode 100644 index 82603f0d5..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/InterceptorParserHander.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import com.taobao.arthas.bytekit.asm.interceptor.parser.InterceptorProcessorParser; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@java.lang.annotation.Target(ElementType.ANNOTATION_TYPE) -public @interface InterceptorParserHander { - - Class parserHander(); - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/InterceptorParserUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/InterceptorParserUtils.java deleted file mode 100644 index 49fab8494..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/InterceptorParserUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorMethodConfig; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.location.LocationMatcher; - -import java.lang.reflect.Method; -import java.util.List; - -public class InterceptorParserUtils { - - public static InterceptorProcessor createInterceptorProcessor( - Method method, - LocationMatcher locationMatcher, - boolean inline, - Class suppress, - Class suppressHandler) { - - InterceptorProcessor interceptorProcessor = new InterceptorProcessor(method.getDeclaringClass().getClassLoader()); - - //locationMatcher - interceptorProcessor.setLocationMatcher(locationMatcher); - - //interceptorMethodConfig - InterceptorMethodConfig interceptorMethodConfig = new InterceptorMethodConfig(); - interceptorProcessor.setInterceptorMethodConfig(interceptorMethodConfig); - interceptorMethodConfig.setOwner(Type.getInternalName(method.getDeclaringClass())); - interceptorMethodConfig.setMethodName(method.getName()); - interceptorMethodConfig.setMethodDesc(Type.getMethodDescriptor(method)); - - //inline - interceptorMethodConfig.setInline(inline); - - //bindings - List bindings = BindingParserUtils.parseBindings(method); - interceptorMethodConfig.setBindings(bindings); - - //errorHandlerMethodConfig - InterceptorMethodConfig errorHandlerMethodConfig = ExceptionHandlerUtils - .errorHandlerMethodConfig(suppress, suppressHandler); - if (errorHandlerMethodConfig != null) { - interceptorProcessor.setExceptionHandlerConfig(errorHandlerMethodConfig); - } - - return interceptorProcessor; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/None.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/None.java deleted file mode 100644 index f4c87c178..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/None.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -/** - * 用于声明没有异常 - * @author hengyunabc - * - */ -public class None extends Throwable { - private static final long serialVersionUID = 1L; - - private None() { - } -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/PrintSuppressHandler.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/PrintSuppressHandler.java deleted file mode 100644 index 191cdb0d3..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/annotation/PrintSuppressHandler.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.annotation; - -import com.taobao.arthas.bytekit.asm.binding.Binding; - -public class PrintSuppressHandler { - - @ExceptionHandler(inline = true) - public static void onSuppress(@Binding.Throwable Throwable e) { - e.printStackTrace(); - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/DefaultInterceptorClassParser.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/DefaultInterceptorClassParser.java deleted file mode 100644 index f1c703449..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/DefaultInterceptorClassParser.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.parser; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.List; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.InterceptorParserHander; -import com.taobao.arthas.bytekit.utils.InstanceUtils; -import com.taobao.arthas.bytekit.utils.ReflectionUtils; -import com.taobao.arthas.bytekit.utils.ReflectionUtils.MethodCallback; - -public class DefaultInterceptorClassParser implements InterceptorClassParser { - - @Override - public List parse(Class clazz) { - final List result = new ArrayList(); - - MethodCallback methodCallback = new MethodCallback() { - - @Override - public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - for (Annotation onMethodAnnotation : method.getAnnotations()) { - for (Annotation onAnnotation : onMethodAnnotation.annotationType().getAnnotations()) { - if (InterceptorParserHander.class.isAssignableFrom(onAnnotation.annotationType())) { - - if (!Modifier.isStatic(method.getModifiers())) { - throw new IllegalArgumentException("method must be static. method: " + method); - } - - InterceptorParserHander handler = (InterceptorParserHander) onAnnotation; - InterceptorProcessorParser interceptorProcessorParser = InstanceUtils - .newInstance(handler.parserHander()); - InterceptorProcessor interceptorProcessor = interceptorProcessorParser.parse(method, - onMethodAnnotation); - result.add(interceptorProcessor); - } - } - } - } - - }; - ReflectionUtils.doWithMethods(clazz, methodCallback); - - return result; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/InterceptorClassParser.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/InterceptorClassParser.java deleted file mode 100644 index e28c66eb0..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/InterceptorClassParser.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.parser; - -import java.util.List; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; - -public interface InterceptorClassParser { - - public List parse(Class clazz); -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/InterceptorProcessorParser.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/InterceptorProcessorParser.java deleted file mode 100644 index 233ff4d24..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/interceptor/parser/InterceptorProcessorParser.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor.parser; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; - -public interface InterceptorProcessorParser { - - public InterceptorProcessor parse(Method method, Annotation annotationOnMethod); -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/AccessLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/AccessLocationMatcher.java deleted file mode 100644 index e773b781a..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/AccessLocationMatcher.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -public abstract class AccessLocationMatcher implements LocationMatcher { - protected int count; - - /** - * flags identifying which type of access should be used to identify the - * trigger. this is either ACCESS_READ, ACCESS_WRITE or an OR of these two - * values - */ - protected int flags; - - /** - * flag which is false if the trigger should be inserted before the field - * access is performed and true if it should be inserted after - */ - protected boolean whenComplete; - - AccessLocationMatcher(int count, int flags, boolean whenComplete) { - this.count = count; - this.flags = flags; - this.whenComplete = whenComplete; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/EnterLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/EnterLocationMatcher.java deleted file mode 100644 index ccb93b672..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/EnterLocationMatcher.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.location.Location.EnterLocation; -import com.taobao.arthas.bytekit.asm.location.filter.LocationFilter; - -public class EnterLocationMatcher implements LocationMatcher { - - @Override - public List match(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - AbstractInsnNode enterInsnNode = methodProcessor.getEnterInsnNode(); - - LocationFilter locationFilter = methodProcessor.getLocationFilter(); - if (locationFilter.allow(enterInsnNode, LocationType.ENTER, true)) { - EnterLocation enterLocation = new EnterLocation(enterInsnNode); - locations.add(enterLocation); - } - return locations; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ExceptionExitLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ExceptionExitLocationMatcher.java deleted file mode 100644 index 88fa9343c..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ExceptionExitLocationMatcher.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LabelNode; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.TryCatchBlock; -import com.taobao.arthas.bytekit.asm.location.Location.ExceptionExitLocation; -import com.taobao.arthas.bytekit.asm.location.filter.LocationFilter; - -public class ExceptionExitLocationMatcher implements LocationMatcher { - - private String exception; - - public ExceptionExitLocationMatcher() { - this(Type.getType(Throwable.class).getInternalName()); - } - - public ExceptionExitLocationMatcher(String exception) { - this.exception = exception; - } - - @Override - public List match(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - TryCatchBlock tryCatchBlock = methodProcessor.initTryCatchBlock(exception); - - LabelNode endLabelNode = tryCatchBlock.getEndLabelNode(); - - LocationFilter locationFilter = methodProcessor.getLocationFilter(); - if (locationFilter.allow(endLabelNode, LocationType.EXCEPTION_EXIT, false)) { - locations.add(new ExceptionExitLocation(tryCatchBlock.getEndLabelNode())); - } - return locations; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ExitLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ExitLocationMatcher.java deleted file mode 100644 index c532ad123..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ExitLocationMatcher.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.location.Location.ExitLocation; -import com.taobao.arthas.bytekit.asm.location.filter.LocationFilter; - -public class ExitLocationMatcher implements LocationMatcher { - - @Override - public List match(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode(); - - while (insnNode != null) { - if (insnNode instanceof InsnNode) { - InsnNode node = (InsnNode) insnNode; - if (matchExit(node)) { - LocationFilter locationFilter = methodProcessor.getLocationFilter(); - if (locationFilter.allow(node, LocationType.EXIT, false)) { - ExitLocation ExitLocation = new ExitLocation(node); - locations.add(ExitLocation); - } - } - } - insnNode = insnNode.getNext(); - } - - return locations; - } - - public boolean matchExit(InsnNode node) { - switch (node.getOpcode()) { - case Opcodes.RETURN: // empty stack - case Opcodes.IRETURN: // 1 before n/a after - case Opcodes.FRETURN: // 1 before n/a after - case Opcodes.ARETURN: // 1 before n/a after - case Opcodes.LRETURN: // 2 before n/a after - case Opcodes.DRETURN: // 2 before n/a after - return true; - } - return false; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/FieldAccessLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/FieldAccessLocationMatcher.java deleted file mode 100644 index fa537e8f3..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/FieldAccessLocationMatcher.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.FieldInsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.location.Location.FieldAccessLocation; - -public class FieldAccessLocationMatcher extends AccessLocationMatcher { - - /** - * maybe null - */ - private String ownerClass; - - /** - * the name of the field being accessed at the point where the trigger point - * should be inserted - */ - private String fieldName; - - /** - * The field's descriptor (see {@link org.objectweb.asm.Type}). maybe null. - */ - private String fieldDesc; - - - public FieldAccessLocationMatcher(String ownerClass, String fieldDesc, String fieldName, int count, int flags, - boolean whenComplete) { - super(count, flags, whenComplete); - this.ownerClass = ownerClass; - this.fieldDesc = fieldDesc; - this.fieldName = fieldName; - } - - @Override - public List match(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode(); - - int matchedCount = 0; - while (insnNode != null) { - if (insnNode instanceof FieldInsnNode) { - FieldInsnNode fieldInsnNode = (FieldInsnNode) insnNode; - - if (matchField(fieldInsnNode)) { - matchedCount++; - if (count <= 0 || count == matchedCount) { - FieldAccessLocation fieldAccessLocation = new FieldAccessLocation(fieldInsnNode, count, flags, whenComplete); - locations.add(fieldAccessLocation); - } - } - } - insnNode = insnNode.getNext(); - } - - return locations; - } - - private boolean matchField(FieldInsnNode fieldInsnNode) { - if (!fieldName.equals(fieldInsnNode.name)) { - return false; - } - - if (this.fieldDesc != null && !this.fieldDesc.equals(fieldInsnNode.desc)) { - return false; - } - - switch (fieldInsnNode.getOpcode()) { - case Opcodes.GETSTATIC: - case Opcodes.GETFIELD: { - if ((flags & Location.ACCESS_READ) == 0) { - return false; - } - } - break; - case Opcodes.PUTSTATIC: - case Opcodes.PUTFIELD: { - if ((flags & Location.ACCESS_WRITE) == 0) { - return false; - } - } - break; - } - if (ownerClass != null) { - if (!ownerClass.equals(fieldInsnNode.owner)) { - return false; - } - } - return true; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/InvokeLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/InvokeLocationMatcher.java deleted file mode 100644 index 844658b29..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/InvokeLocationMatcher.java +++ /dev/null @@ -1,243 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.JumpInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LabelNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.TryCatchBlock; -import com.taobao.arthas.bytekit.asm.location.Location.InvokeExceptionExitLocation; -import com.taobao.arthas.bytekit.asm.location.Location.InvokeLocation; -import com.taobao.arthas.bytekit.asm.location.filter.LocationFilter; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; -import com.taobao.arthas.bytekit.utils.MatchUtils; - -/** - * - * @author hengyunabc - * - */ -public class InvokeLocationMatcher implements LocationMatcher { - - /** - * the name of the method being invoked at the point where the trigger point - * should be inserted. maybe null, when null, match all method invoke. - */ - private String methodName; - - /** - * the name of the type to which the method belongs or null if any type will do - */ - private String owner; - - /** - * the method signature in externalised form, maybe null. - */ - private String desc; - - /** - * count identifying which invocation should be taken as the trigger point. if - * not specified as a parameter this defaults to the first invocation. - */ - private int count; - - /** - * flag which is false if the trigger should be inserted before the method - * invocation is performed and true if it should be inserted after - */ - private boolean whenComplete; - - /** - * wildcard matcher to exclude the invoke class, such as java.* to exclude jdk - * invoke. - */ - private List excludes = new ArrayList(); - - private boolean atInvokeExcpetionExit = false; - - public InvokeLocationMatcher(String owner, String methodName, String desc, int count, boolean whenComplete, - List excludes, boolean atInvokeExcpetionExit) { - super(); - this.owner = owner; - this.methodName = methodName; - this.desc = desc; - this.count = count; - this.whenComplete = whenComplete; - this.excludes = excludes; - this.atInvokeExcpetionExit = atInvokeExcpetionExit; - } - - public InvokeLocationMatcher(String owner, String methodName, String desc, int count, boolean whenComplete, - List excludes) { - this(owner, methodName, desc, count, whenComplete, excludes, false); - } - - public InvokeLocationMatcher(String owner, String methodName, String desc, int count, boolean whenComplete) { - this(owner, methodName, desc, count, whenComplete, new ArrayList()); - } - - @Override - public List match(MethodProcessor methodProcessor) { - if (this.atInvokeExcpetionExit) { - return matchForException(methodProcessor); - } - List locations = new ArrayList(); - AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode(); - - LocationFilter locationFilter = methodProcessor.getLocationFilter(); - - LocationType locationType = whenComplete ? LocationType.INVOKE_COMPLETED : LocationType.INVOKE; - - int matchedCount = 0; - while (insnNode != null) { - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - - if (matchCall(methodInsnNode)) { - if(locationFilter.allow(methodInsnNode, locationType, this.whenComplete)) { - matchedCount++; - if (count <= 0 || count == matchedCount) { - InvokeLocation invokeLocation = new InvokeLocation(methodInsnNode, count, whenComplete); - locations.add(invokeLocation); - } - } - } - } - insnNode = insnNode.getNext(); - } - - return locations; - } - - public List matchForException(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode(); - - MethodNode methodNode = methodProcessor.getMethodNode(); - - List methodInsnNodes = new ArrayList(); - - LocationFilter locationFilter = methodProcessor.getLocationFilter(); - - LocationType locationType = LocationType.INVOKE_EXCEPTION_EXIT; - - int matchedCount = 0; - while (insnNode != null) { - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - - if (matchCall(methodInsnNode)) { - if(locationFilter.allow(methodInsnNode, locationType, this.whenComplete)) { - matchedCount++; - if (count <= 0 || count == matchedCount) { - methodInsnNodes.add(methodInsnNode); - } - } - } - } - insnNode = insnNode.getNext(); - } - - // insert try/catch - for (MethodInsnNode methodInsnNode : methodInsnNodes) { - TryCatchBlock tryCatchBlock = new TryCatchBlock(methodNode); - - InsnList toInsert = new InsnList(); - - LabelNode gotoDest = new LabelNode(); - - LabelNode startLabelNode = tryCatchBlock.getStartLabelNode(); - LabelNode endLabelNode = tryCatchBlock.getEndLabelNode(); - - toInsert.add(new JumpInsnNode(Opcodes.GOTO, gotoDest)); - toInsert.add(endLabelNode); - AsmOpUtils.throwException(toInsert); - locations.add(new InvokeExceptionExitLocation(methodInsnNode, endLabelNode)); - - toInsert.add(gotoDest); - - methodNode.instructions.insertBefore(methodInsnNode, startLabelNode); - methodNode.instructions.insert(methodInsnNode, toInsert); - - tryCatchBlock.sort(); - } - - return locations; - } - - private boolean matchCall(MethodInsnNode methodInsnNode) { - - if (methodName != null && !methodName.isEmpty()) { - if (!this.methodName.equals(methodInsnNode.name)) { - return false; - } - } - - if (!excludes.isEmpty()) { - String ownerClassName = Type.getObjectType(methodInsnNode.owner).getClassName(); - for (String exclude : excludes) { - if (MatchUtils.wildcardMatch(ownerClassName, exclude)) { - return false; - } - } - } - - if (this.owner != null && !this.owner.equals(methodInsnNode.owner)) { - return false; - } - - if (this.desc != null && !desc.equals(methodInsnNode.desc)) { - return false; - } - - return true; - - } - - public String getMethodName() { - return methodName; - } - - public void setMethodName(String methodName) { - this.methodName = methodName; - } - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - - public boolean isWhenComplete() { - return whenComplete; - } - - public void setWhenComplete(boolean whenComplete) { - this.whenComplete = whenComplete; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LineLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LineLocationMatcher.java deleted file mode 100644 index a4ee285e4..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LineLocationMatcher.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LineNumberNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.location.Location.LineLocation; - -public class LineLocationMatcher implements LocationMatcher { - - private List targetLines = Collections.emptyList(); - - public LineLocationMatcher(int... targetLines) { - if (targetLines != null) { - ArrayList result = new ArrayList(targetLines.length); - for (int targetLine : targetLines) { - result.add(targetLine); - } - this.targetLines = result; - } - } - - public LineLocationMatcher(List targetLines) { - this.targetLines = targetLines; - } - - @Override - public List match(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode(); - while (insnNode != null) { - if (insnNode instanceof LineNumberNode) { - LineNumberNode lineNumberNode = (LineNumberNode) insnNode; - if (match(lineNumberNode.line)) { - locations.add(new LineLocation(lineNumberNode, lineNumberNode.line)); - } - } - insnNode = insnNode.getNext(); - } - - return locations; - } - - private boolean match(int line) { - for (int targetLine : targetLines) { - if (targetLine == -1) { - return true; - } else if (line == targetLine) { - return true; - } - - } - return false; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/Location.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/Location.java deleted file mode 100644 index e024b577d..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/Location.java +++ /dev/null @@ -1,696 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.FieldInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.binding.BindingContext; -import com.taobao.arthas.bytekit.asm.binding.StackSaver; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; - -/** - * Specifies a location in a method at which a rule trigger should be inserted - */ -public abstract class Location { - - AbstractInsnNode insnNode; - - boolean whenComplete = false; - - boolean stackNeedSave = false; - - public Location(AbstractInsnNode insnNode) { - this(insnNode, false); - } - - public Location(AbstractInsnNode insnNode, boolean whenComplete) { - this.insnNode = insnNode; - this.whenComplete = whenComplete; - } - - public boolean isWhenComplete() { - return whenComplete; - } - - public AbstractInsnNode getInsnNode() { - return insnNode; - } - - /** - * 标记在这个location,栈上原来的值可以被 callback 函数的return值替换掉 - * - * @return - */ - public boolean canChangeByReturn() { - return false; - } - - public boolean isStackNeedSave() { - return stackNeedSave; - } - - public StackSaver getStackSaver() { - throw new UnsupportedOperationException("this location do not StackSaver, type:" + getLocationType()); - } - - /** - * identify the type of this location - * - * @return the type of this location - */ - public abstract LocationType getLocationType(); - - /** - * flag indicating that a field access location refers to field READ operations - */ - public static final int ACCESS_READ = 1; - - /** - * flag indicating that a field access location refers to field WRITE operations - */ - public static final int ACCESS_WRITE = 2; - - /** - * location identifying a method enter trigger point - */ - static class EnterLocation extends Location { - public EnterLocation(AbstractInsnNode enterInsnNode) { - super(enterInsnNode); - this.insnNode = enterInsnNode; - } - - public LocationType getLocationType() { - return LocationType.ENTER; - } - - } - - /** - * location identifying a method line trigger point - */ - public static class LineLocation extends Location { - /** - * the line at which the trigger point should be inserted - */ - private int targetLine; - - public LineLocation(AbstractInsnNode insnNode, int targetLine) { - super(insnNode); - this.targetLine = targetLine; - } - - public LocationType getLocationType() { - return LocationType.LINE; - } - - } - - /** - * location identifying a generic access trigger point - */ - private static abstract class AccessLocation extends Location { - /** - * count identifying which access should be taken as the trigger point. if not - * specified as a parameter this defaults to the first access. - */ - protected int count; - - /** - * flags identifying which type of access should be used to identify the - * trigger. this is either ACCESS_READ, ACCESS_WRITE or an OR of these two - * values - */ - protected int flags; - - protected AccessLocation(AbstractInsnNode insnNode, int count, int flags, boolean whenComplete) { - super(insnNode, whenComplete); - this.count = count; - this.flags = flags; - } - - public LocationType getLocationType() { - if ((flags & ACCESS_WRITE) != 0) { - if (whenComplete) { - return LocationType.WRITE_COMPLETED; - } else { - return LocationType.WRITE; - } - } else { - if (whenComplete) { - return LocationType.READ_COMPLETED; - } else { - return LocationType.READ; - } - } - } - } - - /** - * location identifying a field access trigger point - */ - public static class FieldAccessLocation extends AccessLocation { - - public FieldAccessLocation(FieldInsnNode fieldInsnNode, int count, int flags, boolean whenComplete) { - super(fieldInsnNode, count, flags, whenComplete); - } - - } - - /** - * location identifying a variable access trigger point - */ - private static class VariableAccessLocation extends AccessLocation { - /** - * the name of the variable being accessed at the point where the trigger point - * should be inserted - */ - private String variableName; - - /** - * flag which is true if the name is a method parameter index such as $0, $1 etc - * otherwise false - */ - private boolean isIndex; - - protected VariableAccessLocation(AbstractInsnNode insnNode, String variablename, int count, int flags, - boolean whenComplete) { - super(insnNode, count, flags, whenComplete); - this.variableName = variablename; - isIndex = variablename.matches("[0-9]+"); - } - - public LocationType getLocationType() { - if ((flags & ACCESS_WRITE) != 0) { - if (whenComplete) { - return LocationType.WRITE_COMPLETED; - } else { - return LocationType.WRITE; - } - } else { - if (whenComplete) { - return LocationType.READ_COMPLETED; - } else { - return LocationType.READ; - } - } - } - - } - - /** - * location identifying a method invocation trigger point - */ - public static class InvokeLocation extends Location implements MethodInsnNodeWare { - - /** - * count identifying which invocation should be taken as the trigger point. if - * not specified as a parameter this defaults to the first invocation. - */ - private int count; - - public InvokeLocation(MethodInsnNode insnNode, int count, boolean whenComplete) { - super(insnNode, whenComplete); - this.count = count; - this.stackNeedSave = false; - } - - @Override - public boolean canChangeByReturn() { - // 对于 invoke ,只有在 complete 时,才能有返回值 - return whenComplete; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - - public LocationType getLocationType() { - if (whenComplete) { - return LocationType.INVOKE_COMPLETED; - } else { - return LocationType.INVOKE; - } - } - - @Override - public StackSaver getStackSaver() { - StackSaver stackSaver = null; - if(whenComplete) { - stackSaver = new StackSaver() { - - @Override - public void store(InsnList instructions, BindingContext bindingContext) { - AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode(); - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - String uniqueNameForMethod = AsmUtils.uniqueNameForMethod(methodInsnNode.owner, methodInsnNode.name, - methodInsnNode.desc); - Type invokeReturnType = Type.getMethodType(methodInsnNode.desc).getReturnType(); - - if(!invokeReturnType.equals(Type.VOID_TYPE)) { - LocalVariableNode invokeReturnVariableNode = methodProcessor.initInvokeReturnVariableNode( - uniqueNameForMethod, invokeReturnType); - AsmOpUtils.storeVar(instructions, invokeReturnType, invokeReturnVariableNode.index); - } - } else { - throw new IllegalArgumentException( - "InvokeReturnBinding location is not MethodInsnNode, insnNode: " + insnNode); - } - - } - - @Override - public void load(InsnList instructions, BindingContext bindingContext) { - AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode(); - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - String uniqueNameForMethod = AsmUtils.uniqueNameForMethod(methodInsnNode.owner, methodInsnNode.name, - methodInsnNode.desc); - Type invokeReturnType = Type.getMethodType(methodInsnNode.desc).getReturnType(); - - if(!invokeReturnType.equals(Type.VOID_TYPE)) { - LocalVariableNode invokeReturnVariableNode = methodProcessor.initInvokeReturnVariableNode( - uniqueNameForMethod, invokeReturnType); - AsmOpUtils.loadVar(instructions, invokeReturnType, invokeReturnVariableNode.index); - } - } else { - throw new IllegalArgumentException( - "InvokeReturnBinding location is not MethodInsnNode, insnNode: " + insnNode); - } - } - - @Override - public Type getType(BindingContext bindingContext) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - return Type.getMethodType(methodInsnNode.desc).getReturnType(); - } - - }; - }else { - stackSaver = new StackSaver() { - - @Override - public void store(InsnList instructions, BindingContext bindingContext) { - // 需要从要调用的 函数的 des ,找到参数的类型,再从栈上一个个吐出来,再保存到数组里 - Location location = bindingContext.getLocation(); - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - if(location instanceof InvokeLocation) { - InvokeLocation invokeLocation = (InvokeLocation) location; - // 如果是非 static的,会有this指针 - MethodInsnNode methodInsnNode = (MethodInsnNode)invokeLocation.getInsnNode(); - Type methodType = Type.getMethodType(methodInsnNode.desc); - boolean isStatic = AsmUtils.isStatic(methodInsnNode); - Type[] argumentTypes = methodType.getArgumentTypes(); - -// // 如果是非static,则存放到数组的index要多 1 -// AsmOpUtils.push(instructions, argumentTypes.length + (isStatic ? 0 : 1)); -// AsmOpUtils.newArray(instructions, AsmOpUtils.OBJECT_TYPE); -// LocalVariableNode invokeArgsVariableNode = methodProcessor.initInvokeArgsVariableNode(); -// AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index); - - // 从invoke的参数的后面,一个个存到数组里 -// for(int i = argumentTypes.length - 1; i >= 0 ; --i) { -// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index); -// -// AsmOpUtils.swap(instructions, argumentTypes[i], AsmOpUtils.OBJECT_ARRAY_TYPE); -// // 如果是非static,则存放到数组的index要多 1 -// AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1)); -// AsmOpUtils.swap(instructions, argumentTypes[i], Type.INT_TYPE); -// -// AsmOpUtils.box(instructions, argumentTypes[i]); -// AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE); -// -// } - // 处理this -// if(!isStatic) { -// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index); -// -// AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, AsmOpUtils.OBJECT_ARRAY_TYPE); -// AsmOpUtils.push(instructions, 0); -// AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, Type.INT_TYPE); -// AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE); -// } - - }else { - throw new IllegalArgumentException("location is not a InvokeLocation, location: " + location); - } - - } - - @Override - public void load(InsnList instructions, BindingContext bindingContext) { - // 从数组里取出来,一个个再放到栈上,要检查是否要unbox - Location location = bindingContext.getLocation(); - MethodProcessor methodProcessor = bindingContext.getMethodProcessor(); - LocalVariableNode invokeArgsVariableNode = methodProcessor.initInvokeArgsVariableNode(); - - if(location instanceof InvokeLocation) { - InvokeLocation invokeLocation = (InvokeLocation) location; - // 如果是非 static的,会有this指针 - MethodInsnNode methodInsnNode = (MethodInsnNode)invokeLocation.getInsnNode(); - Type methodType = Type.getMethodType(methodInsnNode.desc); - boolean isStatic = AsmUtils.isStatic(methodInsnNode); - Type[] argumentTypes = methodType.getArgumentTypes(); - -// if(!isStatic) { -// // 取出this -// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index); -// AsmOpUtils.push(instructions, 0); -// AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE); -// AsmOpUtils.checkCast(instructions, Type.getObjectType(methodInsnNode.owner)); -// } -// -// for(int i = 0; i < argumentTypes.length; ++i) { -// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index); -// AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1)); -// AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE); -// // TODO 这里直接 unbox 就可以了??unbox里带有 check cast -// if(AsmOpUtils.needBox(argumentTypes[i])) { -// AsmOpUtils.unbox(instructions, argumentTypes[i]); -// }else { -// AsmOpUtils.checkCast(instructions, argumentTypes[i]); -// } -// } - - }else { - throw new IllegalArgumentException("location is not a InvokeLocation, location: " + location); - } - } - - @Override - public Type getType(BindingContext bindingContext) { - throw new UnsupportedOperationException("InvokeLocation saver do not support getType()"); - } - - }; - } - - return stackSaver; - } - - @Override - public MethodInsnNode methodInsnNode() { - return (MethodInsnNode) insnNode; - } - - } - - /** - * location identifying a synchronization trigger point - */ - public static class SyncEnterLocation extends Location { - /** - * count identifying which synchronization should be taken as the trigger point. - * if not specified as a parameter this defaults to the first synchronization. - */ - private int count; - - public SyncEnterLocation(AbstractInsnNode insnNode, int count, boolean whenComplete) { - super(insnNode, whenComplete); - this.count = count; - this.whenComplete = whenComplete; - this.stackNeedSave = !whenComplete; - } - - public LocationType getLocationType() { - if (whenComplete) { - return LocationType.SYNC_ENTER_COMPLETED; - } else { - return LocationType.SYNC_ENTER; - } - } - - @Override - public StackSaver getStackSaver() { - return new StackSaver() { - - @Override - public void store(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode variableNode = bindingContext.getMethodProcessor().initMonitorVariableNode(); - AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_TYPE, variableNode.index); - } - - @Override - public void load(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode variableNode = bindingContext.getMethodProcessor().initMonitorVariableNode(); - AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_TYPE, variableNode.index); - } - - @Override - public Type getType(BindingContext bindingContext) { - return AsmOpUtils.OBJECT_TYPE; - } - - }; - } - } - - /** - * location identifying a synchronization trigger point - */ - public static class SyncExitLocation extends Location { - /** - * count identifying which synchronization should be taken as the trigger point. - * if not specified as a parameter this defaults to the first synchronization. - */ - private int count; - - public SyncExitLocation(AbstractInsnNode insnNode, int count, boolean whenComplete) { - super(insnNode, whenComplete); - this.count = count; - this.whenComplete = whenComplete; - this.stackNeedSave = !whenComplete; - } - - public LocationType getLocationType() { - if (whenComplete) { - return LocationType.SYNC_ENTER_COMPLETED; - } else { - return LocationType.SYNC_ENTER; - } - } - - @Override - public StackSaver getStackSaver() { - return new StackSaver() { - - @Override - public void store(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode variableNode = bindingContext.getMethodProcessor().initMonitorVariableNode(); - AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_TYPE, variableNode.index); - } - - @Override - public void load(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode variableNode = bindingContext.getMethodProcessor().initMonitorVariableNode(); - AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_TYPE, variableNode.index); - } - - @Override - public Type getType(BindingContext bindingContext) { - return AsmOpUtils.OBJECT_TYPE; - } - - }; - } - } - - /** - * location identifying a throw trigger point - */ - public static class ThrowLocation extends Location { - /** - * count identifying which throw operation should be taken as the trigger point. - * if not specified as a parameter this defaults to the first throw. - */ - private int count; - - public ThrowLocation(AbstractInsnNode insnNode, int count) { - super(insnNode); - this.count = count; - stackNeedSave = true; - } - - @Override - public boolean canChangeByReturn() { - return true; - } - - public LocationType getLocationType() { - return LocationType.THROW; - } - - public StackSaver getStackSaver() { - StackSaver stackSaver = new StackSaver() { - - @Override - public void store(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode(); - AsmOpUtils.storeVar(instructions, Type.getType(Throwable.class), throwVariableNode.index); - - } - - @Override - public void load(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode(); - AsmOpUtils.loadVar(instructions, Type.getType(Throwable.class), throwVariableNode.index); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(Throwable.class); - } - - }; - return stackSaver; - } - } - - /** - * location identifying a method exit trigger point - */ - public static class ExitLocation extends Location { - - public ExitLocation(AbstractInsnNode insnNode) { - super(insnNode); - stackNeedSave = true; - } - - @Override - public boolean canChangeByReturn() { - return true; - } - - public LocationType getLocationType() { - return LocationType.EXIT; - } - - public StackSaver getStackSaver() { - StackSaver stackSaver = new StackSaver() { - - @Override - public void store(InsnList instructions, BindingContext bindingContext) { - Type returnType = bindingContext.getMethodProcessor().getReturnType(); - if(!returnType.equals(Type.VOID_TYPE)) { - LocalVariableNode returnVariableNode = bindingContext.getMethodProcessor().initReturnVariableNode(); - AsmOpUtils.storeVar(instructions, returnType, returnVariableNode.index); - } - } - - @Override - public void load(InsnList instructions, BindingContext bindingContext) { - Type returnType = bindingContext.getMethodProcessor().getReturnType(); - if(!returnType.equals(Type.VOID_TYPE)) { - LocalVariableNode returnVariableNode = bindingContext.getMethodProcessor().initReturnVariableNode(); - AsmOpUtils.loadVar(instructions, returnType, returnVariableNode.index); - } - } - - @Override - public Type getType(BindingContext bindingContext) { - return bindingContext.getMethodProcessor().getReturnType(); - } - - }; - return stackSaver; - } - - } - - /** - * location identifying a method exceptional exit trigger point - */ - public static class ExceptionExitLocation extends Location{ - public ExceptionExitLocation(AbstractInsnNode insnNode) { - super(insnNode, true); - stackNeedSave = true; - } - - public LocationType getLocationType() { - return LocationType.EXCEPTION_EXIT; - } - - public StackSaver getStackSaver() { - StackSaver stackSaver = new StackSaver() { - - @Override - public void store(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode(); - AsmOpUtils.storeVar(instructions, Type.getType(Throwable.class), throwVariableNode.index); - - } - - @Override - public void load(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode(); - AsmOpUtils.loadVar(instructions, Type.getType(Throwable.class), throwVariableNode.index); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(Throwable.class); - } - - }; - return stackSaver; - } - } - - /** - * location identifying a method exceptional exit trigger point - */ - public static class InvokeExceptionExitLocation extends Location implements MethodInsnNodeWare { - private MethodInsnNode methodInsnNode; - - public InvokeExceptionExitLocation(MethodInsnNode methodInsnNode, AbstractInsnNode insnNode) { - super(insnNode, true); - stackNeedSave = true; - this.methodInsnNode = methodInsnNode; - } - - public LocationType getLocationType() { - return LocationType.INVOKE_EXCEPTION_EXIT; - } - - public StackSaver getStackSaver() { - StackSaver stackSaver = new StackSaver() { - - @Override - public void store(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode(); - AsmOpUtils.storeVar(instructions, Type.getType(Throwable.class), throwVariableNode.index); - - } - - @Override - public void load(InsnList instructions, BindingContext bindingContext) { - LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode(); - AsmOpUtils.loadVar(instructions, Type.getType(Throwable.class), throwVariableNode.index); - } - - @Override - public Type getType(BindingContext bindingContext) { - return Type.getType(Throwable.class); - } - - }; - return stackSaver; - } - - @Override - public MethodInsnNode methodInsnNode() { - return methodInsnNode; - } - } -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LocationMatcher.java deleted file mode 100644 index c37746244..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LocationMatcher.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.List; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; - -public interface LocationMatcher { - - public List match(MethodProcessor methodProcessor); - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LocationType.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LocationType.java deleted file mode 100644 index b2d0b1c61..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/LocationType.java +++ /dev/null @@ -1,91 +0,0 @@ - -package com.taobao.arthas.bytekit.asm.location; - -public enum LocationType { - /** - * user define. - */ - USER_DEFINE, - - /** - * method enter. - * - */ - ENTER, - /** - * line number. - * - */ - LINE, - /** - * field read operation. - * - */ - READ, - /** - * field read operation. - */ - READ_COMPLETED, - /** - * field write operation. - * - */ - WRITE, - /** - * field write operation. - * - */ - WRITE_COMPLETED, - /** - * method invoke operation - * - */ - INVOKE, - /** - * method invoke operation - * - */ - INVOKE_COMPLETED, - - /** - * method invoke exception - */ - INVOKE_EXCEPTION_EXIT, - /** - * synchronize operation - * - */ - SYNC_ENTER, - /** - * synchronize operation - * - */ - SYNC_ENTER_COMPLETED, - - /** - * synchronize operation - * - */ - SYNC_EXIT, - /** - * synchronize operation - * - */ - SYNC_EXIT_COMPLETED, - - /** - * throw - */ - THROW, - - /** - * return - */ - EXIT, - - /** - * add try/catch - */ - EXCEPTION_EXIT; - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/MatchResult.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/MatchResult.java deleted file mode 100644 index 77c31c016..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/MatchResult.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.List; - -public class MatchResult { - - List locations; - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/MethodInsnNodeWare.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/MethodInsnNodeWare.java deleted file mode 100644 index d3d0d6fe7..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/MethodInsnNodeWare.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; - -public interface MethodInsnNodeWare { - - public MethodInsnNode methodInsnNode(); -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/SyncExitLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/SyncExitLocationMatcher.java deleted file mode 100644 index bd38e7de4..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/SyncExitLocationMatcher.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.location.Location.SyncEnterLocation; - -public class SyncExitLocationMatcher implements LocationMatcher { - - private int count; - - boolean whenComplete; - - public SyncExitLocationMatcher(int count, boolean whenComplete) { - this.count = count; - this.whenComplete = whenComplete; - } - - @Override - public List match(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode(); - - int matchedCount = 0; - while (insnNode != null) { - if (insnNode instanceof InsnNode) { - InsnNode node = (InsnNode) insnNode; - if (node.getOpcode() == Opcodes.MONITOREXIT) { - ++matchedCount; - if (count <= 0 || count == matchedCount) { - SyncEnterLocation location = new SyncEnterLocation(node, matchedCount, whenComplete); - locations.add(location); - } - } - } - insnNode = insnNode.getNext(); - } - - return locations; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/SyncLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/SyncLocationMatcher.java deleted file mode 100644 index 119573126..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/SyncLocationMatcher.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.location.Location.SyncEnterLocation; - -public class SyncLocationMatcher implements LocationMatcher { - - private int count; - - boolean whenComplete; - - int opcode; - - public SyncLocationMatcher(int opcode, int count, boolean whenComplete) { - if (!(Opcodes.MONITORENTER == opcode || Opcodes.MONITOREXIT == opcode)) { - throw new IllegalArgumentException( - "SyncLocationMatcher only support Opcodes.MONITORENTER or Opcodes.MONITOREXIT."); - } - this.opcode = opcode; - this.count = count; - this.whenComplete = whenComplete; - } - - @Override - public List match(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode(); - - int matchedCount = 0; - while (insnNode != null) { - if (insnNode instanceof InsnNode) { - InsnNode node = (InsnNode) insnNode; - if (node.getOpcode() == opcode) { - ++matchedCount; - if (count <= 0 || count == matchedCount) { - SyncEnterLocation location = new SyncEnterLocation(node, matchedCount, whenComplete); - locations.add(location); - } - } - } - insnNode = insnNode.getNext(); - } - - return locations; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ThrowLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ThrowLocationMatcher.java deleted file mode 100644 index 3b74e9207..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/ThrowLocationMatcher.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.location.Location.ThrowLocation; - -public class ThrowLocationMatcher implements LocationMatcher { - - public ThrowLocationMatcher(int count) { - this.count = count; - } - - /** - * count identifying which invocation should be taken as the trigger point. - * if not specified as a parameter this defaults to the first invocation. - */ - private int count; - - @Override - public List match(MethodProcessor methodProcessor) { - List locations = new ArrayList(); - AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode(); - - int matchedCount = 0; - while (insnNode != null) { - if (insnNode instanceof InsnNode) { - InsnNode node = (InsnNode) insnNode; - if (node.getOpcode() == Opcodes.ATHROW) { - ++matchedCount; - if (count <= 0 || count == matchedCount) { - ThrowLocation location = new ThrowLocation(node, matchedCount); - locations.add(location); - } - } - } - insnNode = insnNode.getNext(); - } - - return locations; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/VariableAccessLocationMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/VariableAccessLocationMatcher.java deleted file mode 100644 index 590f40a77..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/VariableAccessLocationMatcher.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location; - -import java.util.List; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; - -public class VariableAccessLocationMatcher extends AccessLocationMatcher { - - /** - * the name of the variable being accessed at the point where the trigger - * point should be inserted - */ - private String variableName; - - /** - * flag which is true if the name is a method parameter index such as $0, $1 - * etc otherwise false - */ - private boolean isIndex; - - - protected VariableAccessLocationMatcher(String variablename, int count, int flags, boolean whenComplete) { - super(count, flags, whenComplete); - this.variableName = variablename; - isIndex = variablename.matches("[0-9]+"); - } - - @Override - public List match(MethodProcessor methodProcessor) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/DefaultLocationFilter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/DefaultLocationFilter.java deleted file mode 100644 index 32e73f6ab..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/DefaultLocationFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location.filter; - -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.taobao.arthas.bytekit.asm.location.LocationType; -import com.taobao.arthas.bytekit.utils.MatchUtils; - -/** - * - * @author hengyunabc 2020-05-04 - * - */ -public class DefaultLocationFilter implements LocationFilter { - -// private List signatures; -// -// public DefaultLocationFilter(List signatures) { -// this.signatures = signatures; -// } - - @Override - public boolean allow(AbstractInsnNode insnNode, LocationType locationType, boolean complete) { - return true; - } - -// @Override -// public boolean allow(String signature) { -// for (String s : signatures) { -// if (MatchUtils.wildcardMatch(signature, s)) { -// return false; -// } -// } -// -// return true; -// } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/GroupLocationFilter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/GroupLocationFilter.java deleted file mode 100644 index 9ee6bce64..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/GroupLocationFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location.filter; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.taobao.arthas.bytekit.asm.location.LocationType; - -/** - * - * @author hengyunabc 2020-05-04 - * - */ -public class GroupLocationFilter implements LocationFilter { - - List filters = new ArrayList(); - - public GroupLocationFilter(LocationFilter... filters) { - for (LocationFilter filter : filters) { - this.filters.add(filter); - } - } - - public void addFilter(LocationFilter filter) { - this.filters.add(filter); - } - - @Override - public boolean allow(AbstractInsnNode insnNode, LocationType locationType, boolean complete) { - for (LocationFilter filter : filters) { - if (filter.allow(insnNode, locationType, complete)) { - return true; - } - } - return false; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeCheckLocationFilter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeCheckLocationFilter.java deleted file mode 100644 index 806f62bfd..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeCheckLocationFilter.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location.filter; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.taobao.arthas.bytekit.asm.location.LocationType; - -/** - * - * 检查某个 AbstractInsnNode 的前面是否有某个函数调用,如果有,则认为这个location是已被处理过的 - * - * @author hengyunabc 2020-05-04 - * - */ -public class InvokeCheckLocationFilter implements LocationFilter { - - private String owner; - private String methodName; - private LocationType locationType; - - public InvokeCheckLocationFilter(String owner, String methodName, LocationType locationType) { - this.owner = owner; - this.methodName = methodName; - this.locationType = locationType; - } - - @Override - public boolean allow(AbstractInsnNode insnNode, LocationType locationType, boolean complete) { - // 只检查自己对应的 LocationType - if (!this.locationType.equals(locationType)) { - return false; - } - - MethodInsnNode methodInsnNode = findMethodInsnNode(insnNode, complete); - if (methodInsnNode != null) { - if (methodInsnNode.owner.equals(this.owner) && methodInsnNode.name.equals(this.methodName)) { - return false; - } - } - - return true; - } - - private MethodInsnNode findMethodInsnNode(AbstractInsnNode insnNode, boolean complete) { - if (complete) { - while (insnNode != null) { - insnNode = insnNode.getNext(); - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - return methodInsnNode; - } - } - } else { - while (insnNode != null) { - insnNode = insnNode.getPrevious(); - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - return methodInsnNode; - } - } - } - return null; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeContainLocationFilter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeContainLocationFilter.java deleted file mode 100644 index af59fbefe..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeContainLocationFilter.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location.filter; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.taobao.arthas.bytekit.asm.location.LocationType; - -/** - * - * 检查整个method里,是否有某个函数调用。用于检查 enter/exit/exception exit - * - * @author hengyunabc 2020-05-04 - * - */ -public class InvokeContainLocationFilter implements LocationFilter { - - private String owner; - private String methodName; - private LocationType locationType; - - public InvokeContainLocationFilter(String owner, String methodName, LocationType locationType) { - this.owner = owner; - this.methodName = methodName; - this.locationType = locationType; - } - - @Override - public boolean allow(AbstractInsnNode insnNode, LocationType locationType, boolean complete) { - // 只检查自己对应的 LocationType - if (!this.locationType.equals(locationType)) { - return false; - } - - MethodInsnNode methodInsnNode = findMethodInsnNode(insnNode); - if (methodInsnNode != null) { - if (methodInsnNode.owner.equals(this.owner) && methodInsnNode.name.equals(this.methodName)) { - return false; - } - } - - return true; - } - - private MethodInsnNode findMethodInsnNode(AbstractInsnNode insnNode) { - - AbstractInsnNode current = insnNode; - while (current != null) { - current = current.getNext(); - if (current instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) current; - if (methodInsnNode.owner.equals(this.owner) && methodInsnNode.name.equals(this.methodName)) { - return methodInsnNode; - } - } - } - current = insnNode; - while (current != null) { - current = current.getPrevious(); - if (current instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) current; - if (methodInsnNode.owner.equals(this.owner) && methodInsnNode.name.equals(this.methodName)) { - return methodInsnNode; - } - } - } - return null; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/LocationFilter.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/LocationFilter.java deleted file mode 100644 index ac754b5a3..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/location/filter/LocationFilter.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location.filter; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.taobao.arthas.bytekit.asm.location.LocationType; - -/** - * - * @author hengyunabc 2020-05-04 - * - */ -public interface LocationFilter { - - public boolean allow(AbstractInsnNode insnNode, LocationType locationType, boolean complete); - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/matcher/ClassMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/matcher/ClassMatcher.java deleted file mode 100644 index e9a4b4fbc..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/matcher/ClassMatcher.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.taobao.arthas.bytekit.asm.matcher; - -public interface ClassMatcher { - - boolean match(String name, ClassLoader classLoader); - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/matcher/MethodMatcher.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/matcher/MethodMatcher.java deleted file mode 100644 index 2edc72486..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/asm/matcher/MethodMatcher.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.taobao.arthas.bytekit.asm.matcher; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; - -public interface MethodMatcher { - - boolean match(String className, MethodNode methodNode); -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AgentUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AgentUtils.java deleted file mode 100644 index 84ee37e82..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AgentUtils.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.lang.instrument.ClassDefinition; -import java.lang.instrument.ClassFileTransformer; -import java.lang.instrument.IllegalClassFormatException; -import java.lang.instrument.Instrumentation; -import java.lang.instrument.UnmodifiableClassException; -import java.security.ProtectionDomain; - -import net.bytebuddy.agent.ByteBuddyAgent; - -public class AgentUtils { - - private static class InstrumentationHolder { - static final Instrumentation instance = ByteBuddyAgent.install(); - } - - public static Instrumentation install() { - return InstrumentationHolder.instance; - - } - - public static void redefine(Class clazz, byte[] classFile) - throws ClassNotFoundException, UnmodifiableClassException { - ClassDefinition classDefinition = new ClassDefinition(clazz, classFile); - InstrumentationHolder.instance.redefineClasses(classDefinition); - } - - public static void reTransform(Class clazz, byte[] classFile) throws UnmodifiableClassException { - - SimpleClassFileTransformer transformer = new SimpleClassFileTransformer(clazz.getClassLoader(), clazz.getName(), - classFile); - InstrumentationHolder.instance.addTransformer(transformer, true); - - InstrumentationHolder.instance.retransformClasses(clazz); - InstrumentationHolder.instance.removeTransformer(transformer); - } - - public static class SimpleClassFileTransformer implements ClassFileTransformer { - private byte[] classBuffer; - private ClassLoader classLoader; - private String className; - - public SimpleClassFileTransformer(ClassLoader classLoader, String className, byte[] classBuffer) { - this.classLoader = classLoader; - this.className = className.replace('.', '/'); - this.classBuffer = classBuffer; - } - - @Override - public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, - ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - - if (this.classLoader == loader && className.equals(this.className)) { - return classBuffer; - } - - return null; - - } - - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AnnotationUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AnnotationUtils.java deleted file mode 100644 index 327b610a1..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AnnotationUtils.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -public class AnnotationUtils { - - public static A findAnnotation(Method method, Class annotationType) { - return method.getAnnotation(annotationType); - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmAnnotationUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmAnnotationUtils.java deleted file mode 100644 index 70d381d39..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmAnnotationUtils.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AnnotationNode; - -/** - * - * @author hengyunabc 2020-05-04 - * - */ -public class AsmAnnotationUtils { - - public static List queryAnnotationInfo(List annotations, String annotationType, - String key) { - List result = new ArrayList(); - if (annotations != null) { - for (AnnotationNode annotationNode : annotations) { - if (annotationNode.desc.equals(annotationType)) { - if (annotationNode.values != null) { - Iterator iterator = annotationNode.values.iterator(); - while (iterator.hasNext()) { - String name = (String) iterator.next(); - Object values = iterator.next(); - if (key.equals(name)) { - result.addAll((List) values); - } - } - } - } - } - } - return result; - } - - public static void addAnnotationInfo(List annotations, String annotationType, String key, - String value) { - - AnnotationNode annotationNode = null; - for (AnnotationNode tmp : annotations) { - if (tmp.desc.equals(annotationType)) { - annotationNode = tmp; - } - } - - if (annotationNode == null) { - annotationNode = new AnnotationNode(annotationType); - annotations.add(annotationNode); - } - - if (annotationNode.values == null) { - annotationNode.values = new ArrayList(); - } - - // 查找有没有对应的key - String name = null; - List values = null; - Iterator iterator = annotationNode.values.iterator(); - while (iterator.hasNext()) { - if (key.equals(iterator.next())) { - values = (List) iterator.next(); - } else { - iterator.next(); - } - } - if (values == null) { - values = new ArrayList(); - annotationNode.values.add(key); - annotationNode.values.add(values); - } - if (!values.contains(values)) { - values.add(value); - } - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmOpUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmOpUtils.java deleted file mode 100644 index 81f1a7f85..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmOpUtils.java +++ /dev/null @@ -1,463 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.commons.Method; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.FieldInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.IntInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LdcInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.TypeInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.VarInsnNode; - -public class AsmOpUtils { - - private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte"); - - private static final Type BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean"); - - private static final Type SHORT_TYPE = Type.getObjectType("java/lang/Short"); - - private static final Type CHARACTER_TYPE = Type.getObjectType("java/lang/Character"); - - private static final Type INTEGER_TYPE = Type.getObjectType("java/lang/Integer"); - - private static final Type FLOAT_TYPE = Type.getObjectType("java/lang/Float"); - - private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long"); - - private static final Type DOUBLE_TYPE = Type.getObjectType("java/lang/Double"); - - public static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object"); - - public static final Type OBJECT_ARRAY_TYPE = Type.getType(Object[].class); - - public static final Type STRING_TYPE = Type.getObjectType("java/lang/String"); - - public static final Type STRING_ARRAY_TYPE = Type.getType(String[].class); - - private static final Type NUMBER_TYPE = Type.getObjectType("java/lang/Number"); - - private static final Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()"); - - private static final Method CHAR_VALUE = Method.getMethod("char charValue()"); - - private static final Method BYTE_VALUE = Method.getMethod("byte byteValue()"); - - private static final Method SHORT_VALUE = Method.getMethod("short shortValue()"); - - private static final Method INT_VALUE = Method.getMethod("int intValue()"); - - private static final Method FLOAT_VALUE = Method.getMethod("float floatValue()"); - - private static final Method LONG_VALUE = Method.getMethod("long longValue()"); - - private static final Method DOUBLE_VALUE = Method.getMethod("double doubleValue()"); - - public static boolean isBoxType(final Type type) { - if (BYTE_TYPE.equals(type) || BOOLEAN_TYPE.equals(type) || SHORT_TYPE.equals(type) - || CHARACTER_TYPE.equals(type) || INTEGER_TYPE.equals(type) || FLOAT_TYPE.equals(type) - || LONG_TYPE.equals(type) || DOUBLE_TYPE.equals(type)) { - return true; - } - return false; - } - - public static Type getBoxedType(final Type type) { - switch (type.getSort()) { - case Type.BYTE: - return BYTE_TYPE; - case Type.BOOLEAN: - return BOOLEAN_TYPE; - case Type.SHORT: - return SHORT_TYPE; - case Type.CHAR: - return CHARACTER_TYPE; - case Type.INT: - return INTEGER_TYPE; - case Type.FLOAT: - return FLOAT_TYPE; - case Type.LONG: - return LONG_TYPE; - case Type.DOUBLE: - return DOUBLE_TYPE; - } - return type; - } - - public static Method getUnBoxMethod(final Type type) { - switch (type.getSort()) { - case Type.BYTE: - return BYTE_VALUE; - case Type.BOOLEAN: - return BOOLEAN_VALUE; - case Type.SHORT: - return SHORT_VALUE; - case Type.CHAR: - return CHAR_VALUE; - case Type.INT: - return INT_VALUE; - case Type.FLOAT: - return FLOAT_VALUE; - case Type.LONG: - return LONG_VALUE; - case Type.DOUBLE: - return DOUBLE_VALUE; - } - throw new IllegalArgumentException(type + " is not a primitive type."); - } - - public static void newInstance(final InsnList instructions, final Type type) { - instructions.add(new TypeInsnNode(Opcodes.NEW, type.getInternalName())); - } - - public static void push(InsnList insnList, final int value) { - if (value >= -1 && value <= 5) { - insnList.add(new InsnNode(Opcodes.ICONST_0 + value)); - } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { - insnList.add(new IntInsnNode(Opcodes.BIPUSH, value)); - } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { - insnList.add(new IntInsnNode(Opcodes.SIPUSH, value)); - } else { - insnList.add(new LdcInsnNode(value)); - } - } - - public static void push(InsnList insnList, final String value) { - if (value == null) { - insnList.add(new InsnNode(Opcodes.ACONST_NULL)); - } else { - insnList.add(new LdcInsnNode(value)); - } - } - - public static void pushNUll(InsnList insnList) { - insnList.add(new InsnNode(Opcodes.ACONST_NULL)); - } - - /** - * @see org.objectweb.asm.tree.LdcInsnNode#cst - * @param value - */ - public static void ldc(InsnList insnList, Object value) { - insnList.add(new LdcInsnNode(value)); - } - - public static void newArray(final InsnList insnList, final Type type) { - insnList.add(new TypeInsnNode(Opcodes.ANEWARRAY, type.getInternalName())); - } - - public static void dup(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP)); - } - - public static void dup2(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP2)); - } - - public static void dupX1(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP_X1)); - } - - public static void dupX2(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP_X2)); - } - - /** - * Generates a DUP2_X1 instruction. - */ - public static void dup2X1(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP2_X1)); - } - - /** - * Generates a DUP2_X2 instruction. - */ - public static void dup2X2(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.DUP2_X2)); - } - - - public static void pop(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.POP)); - } - - /** - * Generates a POP2 instruction. - */ - public static void pop2(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.POP2)); - } - - public static void swap(final InsnList insnList) { - insnList.add(new InsnNode(Opcodes.SWAP)); - } - - /** - * Generates the instructions to swap the top two stack values. - * - * @param prev - * type of the top - 1 stack value. - * @param type - * type of the top stack value. - */ - public static void swap(final InsnList insnList, final Type prev, final Type type) { - if (type.getSize() == 1) { - if (prev.getSize() == 1) { - swap(insnList); // same as dupX1(), pop(); - } else { - dupX2(insnList); - pop(insnList); - } - } else { - if (prev.getSize() == 1) { - dup2X1(insnList); - pop2(insnList); - } else { - dup2X2(insnList); - pop2(insnList); - } - } - } - - public static void box(final InsnList instructions, Type type) { - if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { - return; - } - - if (type == Type.VOID_TYPE) { - // push null - instructions.add(new InsnNode(Opcodes.ACONST_NULL)); - } else { - Type boxed = getBoxedType(type); - // new instance. - newInstance(instructions, boxed); - if (type.getSize() == 2) { - // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o - // dupX2 - dupX2(instructions); - // dupX2 - dupX2(instructions); - // pop - pop(instructions); - } else { - // p -> po -> opo -> oop -> o - // dupX1 - dupX1(instructions); - // swap - swap(instructions); - } - invokeConstructor(instructions, boxed, new Method("", Type.VOID_TYPE, new Type[] { type })); - } - } - - public static void invokeConstructor(final InsnList instructions, final Type type, final Method method) { - String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName(); - instructions - .add(new MethodInsnNode(Opcodes.INVOKESPECIAL, owner, method.getName(), method.getDescriptor(), false)); - } - - /** - * - * @param instructions - * @param type - * @see org.objectweb.asm.commons.GeneratorAdapter#unbox(Type) - */ - public static void unbox(final InsnList instructions, Type type) { - Type t = NUMBER_TYPE; - Method sig = null; - switch (type.getSort()) { - case Type.VOID: - return; - case Type.CHAR: - t = CHARACTER_TYPE; - sig = CHAR_VALUE; - break; - case Type.BOOLEAN: - t = BOOLEAN_TYPE; - sig = BOOLEAN_VALUE; - break; - case Type.DOUBLE: - sig = DOUBLE_VALUE; - break; - case Type.FLOAT: - sig = FLOAT_VALUE; - break; - case Type.LONG: - sig = LONG_VALUE; - break; - case Type.INT: - case Type.SHORT: - case Type.BYTE: - sig = INT_VALUE; - } - if (sig == null) { - instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, type.getInternalName())); - } else { - instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, t.getInternalName())); - instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, t.getInternalName(), sig.getName(), - sig.getDescriptor(), false)); - } - } - - public static boolean needBox(Type type) { - switch (type.getSort()) { - case Type.BYTE: - case Type.BOOLEAN: - case Type.SHORT: - case Type.CHAR: - case Type.INT: - case Type.FLOAT: - case Type.LONG: - case Type.DOUBLE: - return true; - } - return false; - } - - public static void getStatic(final InsnList insnList, final Type owner, final String name, final Type type) { - insnList.add(new FieldInsnNode(Opcodes.GETSTATIC, owner.getInternalName(), name, type.getDescriptor())); - } - - /** - * Generates the instruction to push the value of a non static field on the - * stack. - * - * @param owner - * the class in which the field is defined. - * @param name - * the name of the field. - * @param type - * the type of the field. - */ - public static void getField(final InsnList insnList, final Type owner, final String name, final Type type) { - insnList.add(new FieldInsnNode(Opcodes.GETFIELD, owner.getInternalName(), name, type.getDescriptor())); - } - - public static void arrayStore(final InsnList instructions, final Type type) { - instructions.add(new InsnNode(type.getOpcode(Opcodes.IASTORE))); - } - - public static void arrayLoad(final InsnList instructions, final Type type) { - instructions.add(new InsnNode(type.getOpcode(Opcodes.IALOAD))); - } - - - /** - * Generates the instruction to load 'this' on the stack. - * @see org.objectweb.asm.commons.GeneratorAdapter#loadThis() - * @param instructions - */ - public static void loadThis(final InsnList instructions) { - instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); - } - - /** - * Generates the instructions to load all the method arguments on the stack, - * as a single object array. - * - * @see org.objectweb.asm.commons.GeneratorAdapter#loadArgArray() - */ - public static void loadArgArray(final InsnList instructions, MethodNode methodNode) { - boolean isStatic = AsmUtils.isStatic(methodNode); - Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc); - push(instructions, argumentTypes.length); - newArray(instructions, OBJECT_TYPE); - for (int i = 0; i < argumentTypes.length; i++) { - dup(instructions); - push(instructions, i); - loadArg(isStatic, instructions, argumentTypes, i); - box(instructions, argumentTypes[i]); - arrayStore(instructions, OBJECT_TYPE); - } - } - - public static void loadArgs(final InsnList instructions, MethodNode methodNode) { - Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc); - boolean isStatic = AsmUtils.isStatic(methodNode); - for (int i = 0; i < argumentTypes.length; i++) { - loadArg(isStatic, instructions, argumentTypes, i); - } - } - - public static void loadArg(boolean staticAccess, final InsnList instructions, Type[] argumentTypes, int i) { - final int index = getArgIndex(staticAccess, argumentTypes, i); - final Type type = argumentTypes[i]; - instructions.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), index)); - } - - static int getArgIndex(boolean staticAccess, final Type[] argumentTypes, final int arg) { - int index = staticAccess ? 0 : 1; - for (int i = 0; i < arg; i++) { - index += argumentTypes[i].getSize(); - } - return index; - } - - public static void loadVar(final InsnList instructions, Type type, final int index) { - instructions.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), index)); - } - - public static void storeVar(final InsnList instructions, Type type, final int index) { - instructions.add(new VarInsnNode(type.getOpcode(Opcodes.ISTORE), index)); - } - - /** - * Generates a type dependent instruction. - * - * @param opcode - * the instruction's opcode. - * @param type - * the instruction's operand. - */ - private static void typeInsn(final InsnList instructions, final int opcode, final Type type) { - instructions.add(new TypeInsnNode(opcode, type.getInternalName())); - } - - /** - * Generates the instruction to check that the top stack value is of the - * given type. - * - * @param type - * a class or interface type. - */ - public static void checkCast(final InsnList instructions, final Type type) { - if (!type.equals(OBJECT_TYPE)) { - typeInsn(instructions, Opcodes.CHECKCAST, type); - } - } - - public static void throwException(final InsnList instructions) { - instructions.add(new InsnNode(Opcodes.ATHROW)); - } - - public static boolean isReturnCode(final int opcode) { - return opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN; - } - - public static List validVariables(List localVariables, - AbstractInsnNode currentInsnNode) { - List results = new ArrayList(); - - // find out current valid local variables - for (LocalVariableNode localVariableNode : localVariables) { - for (AbstractInsnNode iter = localVariableNode.start; iter != null - && (!iter.equals(localVariableNode.end)); iter = iter.getNext()) { - if (iter.equals(currentInsnNode)) { - results.add(localVariableNode); - break; - } - } - } - - return results; - } -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmUtils.java deleted file mode 100644 index 92b49fc4e..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/AsmUtils.java +++ /dev/null @@ -1,586 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.ClassReader; -import com.alibaba.arthas.deps.org.objectweb.asm.ClassVisitor; -import com.alibaba.arthas.deps.org.objectweb.asm.ClassWriter; -import com.alibaba.arthas.deps.org.objectweb.asm.Label; -import com.alibaba.arthas.deps.org.objectweb.asm.MethodVisitor; -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.commons.ClassRemapper; -import com.alibaba.arthas.deps.org.objectweb.asm.commons.JSRInlinerAdapter; -import com.alibaba.arthas.deps.org.objectweb.asm.commons.Remapper; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.FieldNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LocalVariableNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.TypeInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.util.ASMifier; -import com.alibaba.arthas.deps.org.objectweb.asm.util.TraceClassVisitor; -import com.taobao.arthas.bytekit.asm.ClassLoaderAwareClassWriter; - -/** - * - * @author hengyunabc - * - */ -public class AsmUtils { - - public static ClassNode loadClass(Class clazz) throws IOException { - String resource = clazz.getName().replace('.', '/') + ".class"; - InputStream is = clazz.getClassLoader().getResourceAsStream(resource); - ClassReader cr = new ClassReader(is); - ClassNode classNode = new ClassNode(); - cr.accept(classNode, ClassReader.SKIP_FRAMES); - return classNode; - } - - public static ClassNode toClassNode(byte[] classBytes) { - ClassReader reader = new ClassReader(classBytes); - ClassNode result = new ClassNode(Opcodes.ASM9); - reader.accept(result, ClassReader.SKIP_FRAMES); - return result; - } - - public static ClassReader toClassNode(byte[] classBytes, ClassNode classNode) { - ClassReader reader = new ClassReader(classBytes); - reader.accept(classNode, ClassReader.SKIP_FRAMES); - return reader; - } - - /** - * Generate class bytes from class node. - *
- * NOTE: must pass origin classReader for bytecode optimizations, avoiding JVM metaspace OOM. - * @param classNode - * @param classLoader - * @param classReader origin class reader - * @return - */ - public static byte[] toBytes(ClassNode classNode, ClassLoader classLoader, ClassReader classReader) { - int flags = ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS; - ClassWriter writer = new ClassLoaderAwareClassWriter(classReader, flags, classLoader); - classNode.accept(writer); - return writer.toByteArray(); - } - - public static byte[] toBytes(ClassNode classNode) { - ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - classNode.accept(writer); - return writer.toByteArray(); - } - - public static byte[] renameClass(byte[] classBytes, final String newClassName) { - final String internalName = newClassName.replace('.', '/'); - - ClassReader reader = new ClassReader(classBytes); - ClassWriter writer = new ClassWriter(0); - - class RenameRemapper extends Remapper { - private String className; - - @Override - public String map(String typeName) { - if (typeName.equals(className)) { - return internalName; - } - return super.map(typeName); - } - - public void setClassName(String className) { - this.className = className; - } - } - - final RenameRemapper renameRemapper = new RenameRemapper(); - ClassRemapper adapter = new ClassRemapper(writer, renameRemapper) { - @Override - public void visit(final int version, final int access, final String name, final String signature, - final String superName, final String[] interfaces) { - renameRemapper.setClassName(name); - super.visit(version, access, name, signature, superName, interfaces); - } - }; - reader.accept(adapter, ClassReader.EXPAND_FRAMES); - writer.visitEnd(); - return writer.toByteArray(); - } - - public static void replaceMethod(ClassNode classNode, MethodNode methodNode) { - for (int index = 0; index < classNode.methods.size(); ++index) { - MethodNode tmp = classNode.methods.get(index); - if (tmp.name.equals(methodNode.name) && tmp.desc.equals(methodNode.desc)) { - classNode.methods.set(index, methodNode); - } - } - } - - public static String toASMCode(byte[] bytecode) throws IOException { - return toASMCode(bytecode, true); - } - - public static String toASMCode(byte[] bytecode, boolean debug) throws IOException { - int flags = ClassReader.SKIP_DEBUG; - - if (debug) { - flags = 0; - } - - ClassReader cr = new ClassReader(new ByteArrayInputStream(bytecode)); - StringWriter sw = new StringWriter(); - cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(sw)), flags); - return sw.toString(); - } - - public static String toASMCode(ClassNode classNode) { - StringWriter sw = new StringWriter(); - classNode.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(sw))); - return sw.toString(); - } - - public static String toASMCode(MethodNode methodNode) { - ClassNode classNode = new ClassNode(); - classNode.methods.add(methodNode); - return toASMCode(classNode); - } - - public static MethodNode newMethodNode(MethodNode source) { - return new MethodNode(Opcodes.ASM9, source.access, source.name, source.desc, source.signature, - source.exceptions.toArray(new String[source.exceptions.size()])); - } - - public static MethodNode removeJSRInstructions(MethodNode subjectMethod) { - MethodNode result = newMethodNode(subjectMethod); - subjectMethod.accept(new JSRInlinerAdapter(result, subjectMethod.access, subjectMethod.name, subjectMethod.desc, - subjectMethod.signature, - subjectMethod.exceptions.toArray(new String[subjectMethod.exceptions.size()]))); - return result; - } - - public static ClassNode removeJSRInstructions(ClassNode classNode) { - ClassNode result = new ClassNode(Opcodes.ASM9); - classNode.accept(new ClassVisitor(Opcodes.ASM9, result) { - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, - String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); - return new JSRInlinerAdapter(mv, access, name, desc, signature, exceptions); - } - }); - return result; - } - - public static MethodNode removeLineNumbers(MethodNode methodNode) { - MethodNode result = newMethodNode(methodNode); - methodNode.accept(new MethodVisitor(Opcodes.ASM9, result) { - public void visitLineNumber(int line, Label start) { - } - }); - return result; - } - - public static MethodNode findFirstMethod(Collection methodNodes, String name) { - for (MethodNode methodNode : methodNodes) { - if (methodNode.name.equals(name)) { - return methodNode; - } - } - return null; - } - - public static List findMethods(Collection methodNodes, String name) { - List result = new ArrayList(); - for (MethodNode methodNode : methodNodes) { - if (methodNode.name.equals(name)) { - result.add(methodNode); - } - } - return result; - } - - public static MethodNode findMethod(Collection methodNodes, MethodNode target) { - return findMethod(methodNodes, target.name, target.desc); - } - - public static MethodNode findMethod(Collection methodNodes, String name, String desc) { - for (MethodNode methodNode : methodNodes) { - if (methodNode.name.equals(name) && methodNode.desc.equals(desc)) { - return methodNode; - } - } - return null; - } - - public static AbstractInsnNode findInitConstructorInstruction(MethodNode methodNode) { - int nested = 0; - for (AbstractInsnNode insnNode = methodNode.instructions.getFirst(); insnNode != null; insnNode = insnNode - .getNext()) { - if (insnNode instanceof TypeInsnNode) { - if (insnNode.getOpcode() == Opcodes.NEW) { - // new object(). - nested++; - } - } else if (insnNode instanceof MethodInsnNode) { - final MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - if (methodInsnNode.getOpcode() == Opcodes.INVOKESPECIAL && methodInsnNode.name.equals("")) { - if (--nested < 0) { - // find this() or super(). - return insnNode.getNext(); - } - } - } - } - - return null; - } - - public static List findMethodInsnNodeWithPrefix(MethodNode methodNode, String prefix) { - List result = new ArrayList(); - for (AbstractInsnNode insnNode = methodNode.instructions.getFirst(); insnNode != null; insnNode = insnNode - .getNext()) { - if (insnNode instanceof MethodInsnNode) { - final MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - if(methodInsnNode.name.startsWith(prefix)) { - result.add(methodInsnNode); - } - } - } - return result; - } - - public static List findMethodInsnNode(MethodNode methodNode, String owner, String name) { - List result = new ArrayList(); - for (AbstractInsnNode insnNode = methodNode.instructions.getFirst(); insnNode != null; insnNode = insnNode - .getNext()) { - if (insnNode instanceof MethodInsnNode) { - final MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - if (methodInsnNode.owner.equals(owner) && methodInsnNode.name.equals(name)) { - result.add(methodInsnNode); - } - } - } - return result; - } - public static List findMethodInsnNode(MethodNode methodNode, String owner, String name, - String desc) { - List result = new ArrayList(); - for (AbstractInsnNode insnNode = methodNode.instructions.getFirst(); insnNode != null; insnNode = insnNode - .getNext()) { - if (insnNode instanceof MethodInsnNode) { - final MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - if (methodInsnNode.owner.equals(owner) && methodInsnNode.name.equals(name) - && methodInsnNode.desc.equals(desc)) { - result.add(methodInsnNode); - } - } - } - return result; - } - - public static boolean containsMethodInsnNode(MethodNode methodNode, String owner, String name) { - for (AbstractInsnNode insnNode = methodNode.instructions.getFirst(); insnNode != null; insnNode = insnNode - .getNext()) { - if (insnNode instanceof MethodInsnNode) { - final MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - if (methodInsnNode.owner.equals(owner) && methodInsnNode.name.equals(name)) { - return true; - } - } - } - return false; - } - - public static boolean isStatic(MethodNode methodNode) { - return (methodNode.access & Opcodes.ACC_STATIC) != 0; - } - - public static boolean isStatic(MethodInsnNode methodInsnNode) { - return methodInsnNode.getOpcode() == Opcodes.INVOKESTATIC; - } - - - public static boolean isConstructor(MethodNode methodNode) { - return methodNode.name != null && methodNode.name.equals(""); - } - - - public String[] getParameterNames(MethodNode methodNode) { - Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc); - if (argumentTypes.length == 0) { - return new String[0]; - } - - final List localVariableNodes = methodNode.localVariables; - int localVariableStartIndex = 1; - if (isStatic(methodNode)) { - // static method is none this. - localVariableStartIndex = 0; - } - - if (localVariableNodes == null || localVariableNodes.size() <= localVariableStartIndex || - (argumentTypes.length + localVariableStartIndex) > localVariableNodes.size()) { - // make simple argument names. - final String[] names = new String[argumentTypes.length]; - for (int i = 0; i < argumentTypes.length; i++) { - final String className = argumentTypes[i].getClassName(); - if (className != null) { - final int findIndex = className.lastIndexOf('.'); - if (findIndex == -1) { - names[i] = className; - } else { - names[i] = className.substring(findIndex + 1); - } - } else { - names[i] = argumentTypes[i].getDescriptor(); - } - } - return names; - } - - // sort by index. - Collections.sort(localVariableNodes, new Comparator() { - - @Override - public int compare(LocalVariableNode o1, LocalVariableNode o2) { - return o1.index - o2.index; - } - }); - String[] names = new String[argumentTypes.length]; - - for (int i = 0; i < argumentTypes.length; i++) { - final String name = localVariableNodes.get(localVariableStartIndex++).name; - if (name != null) { - names[i] = name; - } else { - names[i] = ""; - } - } - - return names; - } - - public static MethodNode copy(MethodNode source) { - MethodNode result = newMethodNode(source); - source.accept(result); - return result; - } - - public static ClassNode copy(ClassNode source) { - ClassNode result = new ClassNode(Opcodes.ASM9); - source.accept(new ClassVisitor(Opcodes.ASM9, result) { - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, - String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); - return new JSRInlinerAdapter(mv, access, name, desc, signature, exceptions); - } - }); - return result; - } - - - public static String methodDeclaration(MethodInsnNode methodInsnNode) { - StringBuilder sb = new StringBuilder(128); - - int opcode = methodInsnNode.getOpcode(); - if(opcode == Opcodes.INVOKESTATIC) { - sb.append("static "); - } - Type methodType = Type.getMethodType(methodInsnNode.desc); - Type ownerType = Type.getObjectType(methodInsnNode.owner); - - //skip constructor return type - if(methodInsnNode.name.equals("")) { - sb.append(ownerType.getClassName()); - }else { - sb.append(methodType.getReturnType().getClassName()).append(' '); - sb.append(methodInsnNode.name); - } - - sb.append('('); - Type[] argumentTypes = methodType.getArgumentTypes(); - for(int i = 0 ; i < argumentTypes.length; ++i) { - sb.append(argumentTypes[i].getClassName()); - if(i != argumentTypes.length - 1) { - sb.append(", "); - } - } - sb.append(')'); - return sb.toString(); - - } - - public static String methodDeclaration(Type owner, MethodNode methodNode) { - int access = methodNode.access; - StringBuilder sb = new StringBuilder(128); - -// int ACC_PUBLIC = 0x0001; // class, field, method -// int ACC_PRIVATE = 0x0002; // class, field, method -// int ACC_PROTECTED = 0x0004; // class, field, method -// int ACC_STATIC = 0x0008; // field, method -// int ACC_FINAL = 0x0010; // class, field, method, parameter -// int ACC_SUPER = 0x0020; // class -// int ACC_SYNCHRONIZED = 0x0020; // method -// int ACC_OPEN = 0x0020; // module -// int ACC_TRANSITIVE = 0x0020; // module requires -// int ACC_VOLATILE = 0x0040; // field -// int ACC_BRIDGE = 0x0040; // method -// int ACC_STATIC_PHASE = 0x0040; // module requires -// int ACC_VARARGS = 0x0080; // method -// int ACC_TRANSIENT = 0x0080; // field -// int ACC_NATIVE = 0x0100; // method -// int ACC_INTERFACE = 0x0200; // class -// int ACC_ABSTRACT = 0x0400; // class, method -// int ACC_STRICT = 0x0800; // method -// int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module * -// int ACC_ANNOTATION = 0x2000; // class -// int ACC_ENUM = 0x4000; // class(?) field inner -// int ACC_MANDATED = 0x8000; // parameter, module, module * -// int ACC_MODULE = 0x8000; // class - - if((access & Opcodes.ACC_PUBLIC) != 0) { - sb.append("public "); - } - if((access & Opcodes.ACC_PRIVATE) != 0) { - sb.append("private "); - } - if((access & Opcodes.ACC_PROTECTED) != 0) { - sb.append("protected "); - } - if((access & Opcodes.ACC_STATIC) != 0) { - sb.append("static "); - } - - if((access & Opcodes.ACC_FINAL) != 0) { - sb.append("final "); - } - if((access & Opcodes.ACC_SYNCHRONIZED) != 0) { - sb.append("synchronized "); - } - if((access & Opcodes.ACC_NATIVE) != 0) { - sb.append("native "); - } - if((access & Opcodes.ACC_ABSTRACT) != 0) { - sb.append("abstract "); - } - - Type methodType = Type.getMethodType(methodNode.desc); - - //skip constructor return type - if(methodNode.name.equals("")) { - sb.append(owner.getClassName()); - }else { - sb.append(methodType.getReturnType().getClassName()).append(' '); - sb.append(methodNode.name); - } - - sb.append('('); - Type[] argumentTypes = methodType.getArgumentTypes(); - for(int i = 0 ; i < argumentTypes.length; ++i) { - sb.append(argumentTypes[i].getClassName()); - if(i != argumentTypes.length - 1) { - sb.append(", "); - } - } - sb.append(')'); - if(methodNode.exceptions != null) { - int exceptionSize = methodNode.exceptions.size(); - if( exceptionSize > 0) { - sb.append(" throws"); - for(int i = 0; i < exceptionSize; ++i) { - sb.append(' '); - sb.append(Type.getObjectType(methodNode.exceptions.get(i)).getClassName()); - if(i != exceptionSize -1) { - sb.append(','); - } - } - } - - } - - return sb.toString(); - } - - public static FieldNode findField(List fields, String name) { - for(FieldNode field : fields) { - if(field.name.equals(name)) { - return field; - } - } - return null; - } - - public static void addField(ClassNode classNode, FieldNode fieldNode) { - // TODO 检查是否有重复? - classNode.fields.add(fieldNode); - } - - public static void addMethod(ClassNode classNode, MethodNode methodNode) { - classNode.methods.add(methodNode); - } - - // TODO 是否真的 unique 了? - public static String uniqueNameForMethod(String className, String methodName, String desc) { - StringBuilder result = new StringBuilder(128); - result.append(cleanClassName(className)).append('_').append(methodName); - for(Type arg : Type.getMethodType(desc).getArgumentTypes()) { - result.append('_').append(cleanClassName(arg.getClassName())); - } - return result.toString(); - } - - private static String cleanClassName(String className) { - char[] charArray = className.toCharArray(); - int length = charArray.length; - for(int i = 0 ; i < length; ++i) { - switch( charArray[i]) { - case '[' : - case ']' : - case '<' : - case '>' : - case ';' : - case '/' : - case '.' : - charArray[i] = '_'; - break; - } - } - return new String(charArray); - } - - /** - * Java ClassFile versions (the minor version is stored in the 16 most - * significant bits, and the major version in the 16 least significant bits). - * @see com.alibaba.arthas.deps.org.objectweb.asm.Opcodes#V_PREVIEW - * @param version - * @return - */ - public static int getMajorVersion(int version) { - return 0x0000FFFF & version; - } - - /** - * 替换掉完整 version里的 major version - * - * @param version - * @param majorVersion - * @return - */ - public static int setMajorVersion(int version, int majorVersion) { - return (version & 0xFFFF0000) | majorVersion; - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/ClassLoaderUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/ClassLoaderUtils.java deleted file mode 100644 index 8f5a78a9a..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/ClassLoaderUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.lang.reflect.Field; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; - -import sun.misc.Unsafe; - - -/** - * - * @author hengyunabc 2017-10-12 - * - */ -public class ClassLoaderUtils { - @SuppressWarnings({ "restriction", "unchecked" }) - public static URL[] getUrls(ClassLoader classLoader) { - if (classLoader instanceof URLClassLoader) { - return ((URLClassLoader) classLoader).getURLs(); - } - - // jdk9 - if (classLoader.getClass().getName().startsWith("jdk.internal.loader.ClassLoaders$")) { - try { - Field field = Unsafe.class.getDeclaredField("theUnsafe"); - field.setAccessible(true); - Unsafe unsafe = (Unsafe) field.get(null); - - // jdk.internal.loader.ClassLoaders.AppClassLoader.ucp - Field ucpField = classLoader.getClass().getDeclaredField("ucp"); - long ucpFieldOffset = unsafe.objectFieldOffset(ucpField); - Object ucpObject = unsafe.getObject(classLoader, ucpFieldOffset); - - // jdk.internal.loader.URLClassPath.path - Field pathField = ucpField.getType().getDeclaredField("path"); - long pathFieldOffset = unsafe.objectFieldOffset(pathField); - ArrayList path = (ArrayList) unsafe.getObject(ucpObject, pathFieldOffset); - - return path.toArray(new URL[path.size()]); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - return null; - } -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/Decompiler.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/Decompiler.java deleted file mode 100644 index 1a815208a..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/Decompiler.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; - -import org.benf.cfr.reader.api.CfrDriver; -import org.benf.cfr.reader.api.OutputSinkFactory; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.alibaba.arthas.deps.org.objectweb.asm.util.Printer; -import com.alibaba.arthas.deps.org.objectweb.asm.util.Textifier; -import com.alibaba.arthas.deps.org.objectweb.asm.util.TraceClassVisitor; -import com.alibaba.arthas.deps.org.objectweb.asm.util.TraceMethodVisitor; -import com.taobao.arthas.common.FileUtils; - -/** - * TODO com.taobao.arthas.core.util.Decompiler - * @author hengyunabc - * - */ -public class Decompiler { - - public static String decompile(byte[] bytecode) throws IOException { - String result = ""; - - File tempDirectory = new File(System.getProperty("java.io.tmpdir")); - File file = new File(tempDirectory, UUID.randomUUID().toString()); - FileUtils.writeByteArrayToFile(file, bytecode); - - result = decompile(file.getAbsolutePath(), null); - return result; - } - - public static String decompile(String path) throws IOException { - byte[] byteArray = FileUtils.readFileToByteArray(new File(path)); - return decompile(byteArray); - } - - public static String toString(MethodNode methodNode) { - Printer printer = new Textifier(); - TraceMethodVisitor methodPrinter = new TraceMethodVisitor(printer); - - methodNode.accept(methodPrinter); - - StringWriter sw = new StringWriter(); - printer.print(new PrintWriter(sw)); - printer.getText().clear(); - - return sw.toString(); - } - - public static String toString(ClassNode classNode) { - Printer printer = new Textifier(); - StringWriter sw = new StringWriter(); - PrintWriter printWriter = new PrintWriter(sw); - - TraceClassVisitor traceClassVisitor = new TraceClassVisitor(printWriter); - - classNode.accept(traceClassVisitor); - - printer.print(printWriter); - printer.getText().clear(); - - return sw.toString(); - } - - - - public static String toString(InsnList insnList) { - Printer printer = new Textifier(); - TraceMethodVisitor mp = new TraceMethodVisitor(printer); - insnList.accept(mp); - - StringWriter sw = new StringWriter(); - printer.print(new PrintWriter(sw)); - printer.getText().clear(); - return sw.toString(); - } - - public static String toString(AbstractInsnNode insn) { - Printer printer = new Textifier(); - TraceMethodVisitor mp = new TraceMethodVisitor(printer); - insn.accept(mp); - - StringWriter sw = new StringWriter(); - printer.print(new PrintWriter(sw)); - printer.getText().clear(); - return sw.toString(); - } - - - /** - * @param classFilePath - * @param methodName - * @return - */ - public static String decompile(String classFilePath, String methodName) { - final StringBuilder result = new StringBuilder(8192); - - OutputSinkFactory mySink = new OutputSinkFactory() { - @Override - public List getSupportedSinks(SinkType sinkType, Collection collection) { - return Arrays.asList(SinkClass.STRING, SinkClass.DECOMPILED, SinkClass.DECOMPILED_MULTIVER, - SinkClass.EXCEPTION_MESSAGE); - } - - @Override - public Sink getSink(final SinkType sinkType, SinkClass sinkClass) { - return new Sink() { - @Override - public void write(T sinkable) { - // skip message like: Analysing type demo.MathGame - if (sinkType == SinkType.PROGRESS) { - return; - } - result.append(sinkable); - } - }; - } - }; - - HashMap options = new HashMap(); - /** - * @see org.benf.cfr.reader.util.MiscConstants.Version.getVersion() Currently, - * the cfr version is wrong. so disable show cfr version. - */ - options.put("showversion", "false"); - if (methodName != null) { - options.put("methodname", methodName); - } - - CfrDriver driver = new CfrDriver.Builder().withOptions(options).withOutputSink(mySink).build(); - List toAnalyse = new ArrayList(); - toAnalyse.add(classFilePath); - driver.analyse(toAnalyse); - - return result.toString(); - } - - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/InstanceUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/InstanceUtils.java deleted file mode 100644 index a1526b8f9..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/InstanceUtils.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -public class InstanceUtils { - - public static T newInstance(Class clazz) { - try { - return clazz.newInstance(); - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - } - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/MatchUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/MatchUtils.java deleted file mode 100644 index 077040521..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/MatchUtils.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.taobao.arthas.bytekit.utils; -import java.util.ArrayList; -import java.util.Stack; - -/** - * from org.apache.commons.io.FilenameUtils - * - * @author hengyunabc - * - */ -public class MatchUtils { - - /** - * The wildcard matcher uses the characters '?' and '*' to represent a - * single or multiple wildcard characters. - * - * @param str - * @param wildcardMatcher - * @return - */ - public static boolean wildcardMatch(String str, String wildcardMatcher) { - return wildcardMatch(str, wildcardMatcher, false); - } - - /** - * The wildcard matcher uses the characters '?' and '*' to represent a - * single or multiple wildcard characters. - * - * @param str - * @param wildcardMatcher - * @param sensitive - * if sensitive is true, str and wildcardMatcher will - * toLowerCase. - * @return - */ - public static boolean wildcardMatch(String str, String wildcardMatcher, boolean sensitive) { - if (str == null && wildcardMatcher == null) { - return true; - } - if (str == null || wildcardMatcher == null) { - return false; - } - str = convertCase(str, sensitive); - wildcardMatcher = convertCase(wildcardMatcher, sensitive); - String[] wcs = splitOnTokens(wildcardMatcher); - boolean anyChars = false; - int textIdx = 0; - int wcsIdx = 0; - Stack backtrack = new Stack(); - - // loop around a backtrack stack, to handle complex * matching - do { - if (backtrack.size() > 0) { - int[] array = (int[]) backtrack.pop(); - wcsIdx = array[0]; - textIdx = array[1]; - anyChars = true; - } - - // loop whilst tokens and text left to process - while (wcsIdx < wcs.length) { - - if (wcs[wcsIdx].equals("?")) { - // ? so move to next text char - textIdx++; - anyChars = false; - - } else if (wcs[wcsIdx].equals("*")) { - // set any chars status - anyChars = true; - if (wcsIdx == wcs.length - 1) { - textIdx = str.length(); - } - - } else { - // matching text token - if (anyChars) { - // any chars then try to locate text token - textIdx = str.indexOf(wcs[wcsIdx], textIdx); - if (textIdx == -1) { - // token not found - break; - } - int repeat = str.indexOf(wcs[wcsIdx], textIdx + 1); - if (repeat >= 0) { - backtrack.push(new int[] { wcsIdx, repeat }); - } - } else { - // matching from current position - if (!str.startsWith(wcs[wcsIdx], textIdx)) { - // couldnt match token - break; - } - } - - // matched text token, move text index to end of matched - // token - textIdx += wcs[wcsIdx].length(); - anyChars = false; - } - - wcsIdx++; - } - - // full match - if (wcsIdx == wcs.length && textIdx == str.length()) { - return true; - } - - } while (backtrack.size() > 0); - - return false; - } - - /** - * Splits a string into a number of tokens. - * - * @param text - * the text to split - * @return the tokens, never null - */ - static String[] splitOnTokens(String text) { - // used by wildcardMatch - // package level so a unit test may run on this - - if (text.indexOf("?") == -1 && text.indexOf("*") == -1) { - return new String[] { text }; - } - - char[] array = text.toCharArray(); - ArrayList list = new ArrayList(); - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < array.length; i++) { - if (array[i] == '?' || array[i] == '*') { - if (buffer.length() != 0) { - list.add(buffer.toString()); - buffer.setLength(0); - } - if (array[i] == '?') { - list.add("?"); - } else if (list.size() == 0 || (i > 0 && list.get(list.size() - 1).equals("*") == false)) { - list.add("*"); - } - } else { - buffer.append(array[i]); - } - } - if (buffer.length() != 0) { - list.add(buffer.toString()); - } - - return (String[]) list.toArray(new String[list.size()]); - } - - /** - * Converts the case of the input String to a standard format. Subsequent - * operations can then use standard String methods. - * - * @param str - * the string to convert, null returns null - * @return the lower-case version if case-insensitive - */ - static String convertCase(String str, boolean sensitive) { - if (str == null) { - return null; - } - return sensitive ? str : str.toLowerCase(); - } -} \ No newline at end of file diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/MethodUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/MethodUtils.java deleted file mode 100644 index 8023d3b24..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/MethodUtils.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -public class MethodUtils { - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/ReflectionUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/ReflectionUtils.java deleted file mode 100644 index b96f30b3c..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/ReflectionUtils.java +++ /dev/null @@ -1,807 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * 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.taobao.arthas.bytekit.utils; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.UndeclaredThrowableException; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - -/** - * Simple utility class for working with the reflection API and handling - * reflection exceptions. - * - *

Only intended for internal use. - * - * @author Juergen Hoeller - * @author Rob Harrop - * @author Rod Johnson - * @author Costin Leau - * @author Sam Brannen - * @author Chris Beams - * @since 1.2.2 - */ -public abstract class ReflectionUtils { - - /** - * Naming prefix for CGLIB-renamed methods. - * @see #isCglibRenamedMethod - */ - private static final String CGLIB_RENAMED_METHOD_PREFIX = "CGLIB$"; - - /** - * Attempt to find a {@link Field field} on the supplied {@link Class} with the - * supplied {@code name}. Searches all superclasses up to {@link Object}. - * @param clazz the class to introspect - * @param name the name of the field - * @return the corresponding Field object, or {@code null} if not found - */ - public static Field findField(Class clazz, String name) { - return findField(clazz, name, null); - } - - /** - * Attempt to find a {@link Field field} on the supplied {@link Class} with the - * supplied {@code name} and/or {@link Class type}. Searches all superclasses - * up to {@link Object}. - * @param clazz the class to introspect - * @param name the name of the field (may be {@code null} if type is specified) - * @param type the type of the field (may be {@code null} if name is specified) - * @return the corresponding Field object, or {@code null} if not found - */ - public static Field findField(Class clazz, String name, Class type) { - Class searchType = clazz; - while (Object.class != searchType && searchType != null) { - Field[] fields = getDeclaredFields(searchType); - for (Field field : fields) { - if ((name == null || name.equals(field.getName())) && - (type == null || type.equals(field.getType()))) { - return field; - } - } - searchType = searchType.getSuperclass(); - } - return null; - } - - /** - * Set the field represented by the supplied {@link Field field object} on the - * specified {@link Object target object} to the specified {@code value}. - * In accordance with {@link Field#set(Object, Object)} semantics, the new value - * is automatically unwrapped if the underlying field has a primitive type. - *

Thrown exceptions are handled via a call to {@link #handleReflectionException(Exception)}. - * @param field the field to set - * @param target the target object on which to set the field - * @param value the value to set (may be {@code null}) - */ - public static void setField(Field field, Object target, Object value) { - try { - field.set(target, value); - } - catch (IllegalAccessException ex) { - handleReflectionException(ex); - throw new IllegalStateException( - "Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage()); - } - } - - /** - * Get the field represented by the supplied {@link Field field object} on the - * specified {@link Object target object}. In accordance with {@link Field#get(Object)} - * semantics, the returned value is automatically wrapped if the underlying field - * has a primitive type. - *

Thrown exceptions are handled via a call to {@link #handleReflectionException(Exception)}. - * @param field the field to get - * @param target the target object from which to get the field - * @return the field's current value - */ - public static Object getField(Field field, Object target) { - try { - return field.get(target); - } - catch (IllegalAccessException ex) { - handleReflectionException(ex); - throw new IllegalStateException( - "Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage()); - } - } - - /** - * Attempt to find a {@link Method} on the supplied class with the supplied name - * and no parameters. Searches all superclasses up to {@code Object}. - *

Returns {@code null} if no {@link Method} can be found. - * @param clazz the class to introspect - * @param name the name of the method - * @return the Method object, or {@code null} if none found - */ - public static Method findMethod(Class clazz, String name) { - return findMethod(clazz, name, new Class[0]); - } - - /** - * Attempt to find a {@link Method} on the supplied class with the supplied name - * and parameter types. Searches all superclasses up to {@code Object}. - *

Returns {@code null} if no {@link Method} can be found. - * @param clazz the class to introspect - * @param name the name of the method - * @param paramTypes the parameter types of the method - * (may be {@code null} to indicate any signature) - * @return the Method object, or {@code null} if none found - */ - public static Method findMethod(Class clazz, String name, Class... paramTypes) { - Class searchType = clazz; - while (searchType != null) { - Method[] methods = (searchType.isInterface() ? searchType.getMethods() : getDeclaredMethods(searchType)); - for (Method method : methods) { - if (name.equals(method.getName()) && - (paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) { - return method; - } - } - searchType = searchType.getSuperclass(); - } - return null; - } - - /** - * Invoke the specified {@link Method} against the supplied target object with no arguments. - * The target object can be {@code null} when invoking a static {@link Method}. - *

Thrown exceptions are handled via a call to {@link #handleReflectionException}. - * @param method the method to invoke - * @param target the target object to invoke the method on - * @return the invocation result, if any - * @see #invokeMethod(java.lang.reflect.Method, Object, Object[]) - */ - public static Object invokeMethod(Method method, Object target) { - return invokeMethod(method, target, new Object[0]); - } - - /** - * Invoke the specified {@link Method} against the supplied target object with the - * supplied arguments. The target object can be {@code null} when invoking a - * static {@link Method}. - *

Thrown exceptions are handled via a call to {@link #handleReflectionException}. - * @param method the method to invoke - * @param target the target object to invoke the method on - * @param args the invocation arguments (may be {@code null}) - * @return the invocation result, if any - */ - public static Object invokeMethod(Method method, Object target, Object... args) { - try { - return method.invoke(target, args); - } - catch (Exception ex) { - handleReflectionException(ex); - } - throw new IllegalStateException("Should never get here"); - } - - /** - * Invoke the specified JDBC API {@link Method} against the supplied target - * object with no arguments. - * @param method the method to invoke - * @param target the target object to invoke the method on - * @return the invocation result, if any - * @throws SQLException the JDBC API SQLException to rethrow (if any) - * @see #invokeJdbcMethod(java.lang.reflect.Method, Object, Object[]) - */ - public static Object invokeJdbcMethod(Method method, Object target) throws SQLException { - return invokeJdbcMethod(method, target, new Object[0]); - } - - /** - * Invoke the specified JDBC API {@link Method} against the supplied target - * object with the supplied arguments. - * @param method the method to invoke - * @param target the target object to invoke the method on - * @param args the invocation arguments (may be {@code null}) - * @return the invocation result, if any - * @throws SQLException the JDBC API SQLException to rethrow (if any) - * @see #invokeMethod(java.lang.reflect.Method, Object, Object[]) - */ - public static Object invokeJdbcMethod(Method method, Object target, Object... args) throws SQLException { - try { - return method.invoke(target, args); - } - catch (IllegalAccessException ex) { - handleReflectionException(ex); - } - catch (InvocationTargetException ex) { - if (ex.getTargetException() instanceof SQLException) { - throw (SQLException) ex.getTargetException(); - } - handleInvocationTargetException(ex); - } - throw new IllegalStateException("Should never get here"); - } - - /** - * Handle the given reflection exception. Should only be called if no - * checked exception is expected to be thrown by the target method. - *

Throws the underlying RuntimeException or Error in case of an - * InvocationTargetException with such a root cause. Throws an - * IllegalStateException with an appropriate message or - * UndeclaredThrowableException otherwise. - * @param ex the reflection exception to handle - */ - public static void handleReflectionException(Exception ex) { - if (ex instanceof NoSuchMethodException) { - throw new IllegalStateException("Method not found: " + ex.getMessage()); - } - if (ex instanceof IllegalAccessException) { - throw new IllegalStateException("Could not access method: " + ex.getMessage()); - } - if (ex instanceof InvocationTargetException) { - handleInvocationTargetException((InvocationTargetException) ex); - } - if (ex instanceof RuntimeException) { - throw (RuntimeException) ex; - } - throw new UndeclaredThrowableException(ex); - } - - /** - * Handle the given invocation target exception. Should only be called if no - * checked exception is expected to be thrown by the target method. - *

Throws the underlying RuntimeException or Error in case of such a root - * cause. Throws an UndeclaredThrowableException otherwise. - * @param ex the invocation target exception to handle - */ - public static void handleInvocationTargetException(InvocationTargetException ex) { - rethrowRuntimeException(ex.getTargetException()); - } - - /** - * Rethrow the given {@link Throwable exception}, which is presumably the - * target exception of an {@link InvocationTargetException}. - * Should only be called if no checked exception is expected to be thrown - * by the target method. - *

Rethrows the underlying exception cast to a {@link RuntimeException} or - * {@link Error} if appropriate; otherwise, throws an - * {@link UndeclaredThrowableException}. - * @param ex the exception to rethrow - * @throws RuntimeException the rethrown exception - */ - public static void rethrowRuntimeException(Throwable ex) { - if (ex instanceof RuntimeException) { - throw (RuntimeException) ex; - } - if (ex instanceof Error) { - throw (Error) ex; - } - throw new UndeclaredThrowableException(ex); - } - - /** - * Rethrow the given {@link Throwable exception}, which is presumably the - * target exception of an {@link InvocationTargetException}. - * Should only be called if no checked exception is expected to be thrown - * by the target method. - *

Rethrows the underlying exception cast to an {@link Exception} or - * {@link Error} if appropriate; otherwise, throws an - * {@link UndeclaredThrowableException}. - * @param ex the exception to rethrow - * @throws Exception the rethrown exception (in case of a checked exception) - */ - public static void rethrowException(Throwable ex) throws Exception { - if (ex instanceof Exception) { - throw (Exception) ex; - } - if (ex instanceof Error) { - throw (Error) ex; - } - throw new UndeclaredThrowableException(ex); - } - - /** - * Determine whether the given method explicitly declares the given - * exception or one of its superclasses, which means that an exception - * of that type can be propagated as-is within a reflective invocation. - * @param method the declaring method - * @param exceptionType the exception to throw - * @return {@code true} if the exception can be thrown as-is; - * {@code false} if it needs to be wrapped - */ - public static boolean declaresException(Method method, Class exceptionType) { - Class[] declaredExceptions = method.getExceptionTypes(); - for (Class declaredException : declaredExceptions) { - if (declaredException.isAssignableFrom(exceptionType)) { - return true; - } - } - return false; - } - - /** - * Determine whether the given field is a "public static final" constant. - * @param field the field to check - */ - public static boolean isPublicStaticFinal(Field field) { - int modifiers = field.getModifiers(); - return (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)); - } - - /** - * Determine whether the given method is an "equals" method. - * @see java.lang.Object#equals(Object) - */ - public static boolean isEqualsMethod(Method method) { - if (method == null || !method.getName().equals("equals")) { - return false; - } - Class[] paramTypes = method.getParameterTypes(); - return (paramTypes.length == 1 && paramTypes[0] == Object.class); - } - - /** - * Determine whether the given method is a "hashCode" method. - * @see java.lang.Object#hashCode() - */ - public static boolean isHashCodeMethod(Method method) { - return (method != null && method.getName().equals("hashCode") && method.getParameterTypes().length == 0); - } - - /** - * Determine whether the given method is a "toString" method. - * @see java.lang.Object#toString() - */ - public static boolean isToStringMethod(Method method) { - return (method != null && method.getName().equals("toString") && method.getParameterTypes().length == 0); - } - - /** - * Determine whether the given method is originally declared by {@link java.lang.Object}. - */ - public static boolean isObjectMethod(Method method) { - if (method == null) { - return false; - } - try { - Object.class.getDeclaredMethod(method.getName(), method.getParameterTypes()); - return true; - } - catch (Exception ex) { - return false; - } - } - - /** - * Determine whether the given method is a CGLIB 'renamed' method, - * following the pattern "CGLIB$methodName$0". - * @param renamedMethod the method to check - * @see org.springframework.cglib.proxy.Enhancer#rename - */ - public static boolean isCglibRenamedMethod(Method renamedMethod) { - String name = renamedMethod.getName(); - if (name.startsWith(CGLIB_RENAMED_METHOD_PREFIX)) { - int i = name.length() - 1; - while (i >= 0 && Character.isDigit(name.charAt(i))) { - i--; - } - return ((i > CGLIB_RENAMED_METHOD_PREFIX.length()) && - (i < name.length() - 1) && name.charAt(i) == '$'); - } - return false; - } - - /** - * Make the given field accessible, explicitly setting it accessible if - * necessary. The {@code setAccessible(true)} method is only called - * when actually necessary, to avoid unnecessary conflicts with a JVM - * SecurityManager (if active). - * @param field the field to make accessible - * @see java.lang.reflect.Field#setAccessible - */ - public static void makeAccessible(Field field) { - if ((!Modifier.isPublic(field.getModifiers()) || - !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || - Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) { - field.setAccessible(true); - } - } - - /** - * Make the given method accessible, explicitly setting it accessible if - * necessary. The {@code setAccessible(true)} method is only called - * when actually necessary, to avoid unnecessary conflicts with a JVM - * SecurityManager (if active). - * @param method the method to make accessible - * @see java.lang.reflect.Method#setAccessible - */ - public static void makeAccessible(Method method) { - if ((!Modifier.isPublic(method.getModifiers()) || - !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { - method.setAccessible(true); - } - } - - /** - * Make the given constructor accessible, explicitly setting it accessible - * if necessary. The {@code setAccessible(true)} method is only called - * when actually necessary, to avoid unnecessary conflicts with a JVM - * SecurityManager (if active). - * @param ctor the constructor to make accessible - * @see java.lang.reflect.Constructor#setAccessible - */ - public static void makeAccessible(Constructor ctor) { - if ((!Modifier.isPublic(ctor.getModifiers()) || - !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) && !ctor.isAccessible()) { - ctor.setAccessible(true); - } - } - - /** - * Perform the given callback operation on all matching methods of the given - * class, as locally declared or equivalent thereof (such as default methods - * on Java 8 based interfaces that the given class implements). - * @param clazz the class to introspect - * @param mc the callback to invoke for each method - * @since 4.2 - * @see #doWithMethods - */ - public static void doWithLocalMethods(Class clazz, MethodCallback mc) { - Method[] methods = getDeclaredMethods(clazz); - for (Method method : methods) { - try { - mc.doWith(method); - } - catch (IllegalAccessException ex) { - throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex); - } - } - } - - /** - * Perform the given callback operation on all matching methods of the given - * class and superclasses. - *

The same named method occurring on subclass and superclass will appear - * twice, unless excluded by a {@link MethodFilter}. - * @param clazz the class to introspect - * @param mc the callback to invoke for each method - * @see #doWithMethods(Class, MethodCallback, MethodFilter) - */ - public static void doWithMethods(Class clazz, MethodCallback mc) { - doWithMethods(clazz, mc, null); - } - - /** - * Perform the given callback operation on all matching methods of the given - * class and superclasses (or given interface and super-interfaces). - *

The same named method occurring on subclass and superclass will appear - * twice, unless excluded by the specified {@link MethodFilter}. - * @param clazz the class to introspect - * @param mc the callback to invoke for each method - * @param mf the filter that determines the methods to apply the callback to - */ - public static void doWithMethods(Class clazz, MethodCallback mc, MethodFilter mf) { - // Keep backing up the inheritance hierarchy. - Method[] methods = getDeclaredMethods(clazz); - for (Method method : methods) { - if (mf != null && !mf.matches(method)) { - continue; - } - try { - mc.doWith(method); - } - catch (IllegalAccessException ex) { - throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex); - } - } - if (clazz.getSuperclass() != null) { - doWithMethods(clazz.getSuperclass(), mc, mf); - } - else if (clazz.isInterface()) { - for (Class superIfc : clazz.getInterfaces()) { - doWithMethods(superIfc, mc, mf); - } - } - } - - /** - * Get all declared methods on the leaf class and all superclasses. - * Leaf class methods are included first. - * @param leafClass the class to introspect - */ - public static Method[] getAllDeclaredMethods(Class leafClass) { - final List methods = new ArrayList(32); - doWithMethods(leafClass, new MethodCallback() { - @Override - public void doWith(Method method) { - methods.add(method); - } - }); - return methods.toArray(new Method[methods.size()]); - } - - /** - * Get the unique set of declared methods on the leaf class and all superclasses. - * Leaf class methods are included first and while traversing the superclass hierarchy - * any methods found with signatures matching a method already included are filtered out. - * @param leafClass the class to introspect - */ - public static Method[] getUniqueDeclaredMethods(Class leafClass) { - final List methods = new ArrayList(32); - doWithMethods(leafClass, new MethodCallback() { - @Override - public void doWith(Method method) { - boolean knownSignature = false; - Method methodBeingOverriddenWithCovariantReturnType = null; - for (Method existingMethod : methods) { - if (method.getName().equals(existingMethod.getName()) && - Arrays.equals(method.getParameterTypes(), existingMethod.getParameterTypes())) { - // Is this a covariant return type situation? - if (existingMethod.getReturnType() != method.getReturnType() && - existingMethod.getReturnType().isAssignableFrom(method.getReturnType())) { - methodBeingOverriddenWithCovariantReturnType = existingMethod; - } - else { - knownSignature = true; - } - break; - } - } - if (methodBeingOverriddenWithCovariantReturnType != null) { - methods.remove(methodBeingOverriddenWithCovariantReturnType); - } - if (!knownSignature && !isCglibRenamedMethod(method)) { - methods.add(method); - } - } - }); - return methods.toArray(new Method[methods.size()]); - } - - /** - * This variant retrieves {@link Class#getDeclaredMethods()} from a local cache - * in order to avoid the JVM's SecurityManager check and defensive array copying. - * In addition, it also includes Java 8 default methods from locally implemented - * interfaces, since those are effectively to be treated just like declared methods. - * @param clazz the class to introspect - * @return the cached array of methods - * @see Class#getDeclaredMethods() - */ - private static Method[] getDeclaredMethods(Class clazz) { - Method[] result = null; - if (result == null) { - Method[] declaredMethods = clazz.getDeclaredMethods(); - List defaultMethods = findConcreteMethodsOnInterfaces(clazz); - if (defaultMethods != null) { - result = new Method[declaredMethods.length + defaultMethods.size()]; - System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length); - int index = declaredMethods.length; - for (Method defaultMethod : defaultMethods) { - result[index] = defaultMethod; - index++; - } - } - else { - result = declaredMethods; - } - } - return result; - } - - private static List findConcreteMethodsOnInterfaces(Class clazz) { - List result = null; - for (Class ifc : clazz.getInterfaces()) { - for (Method ifcMethod : ifc.getMethods()) { - if (!Modifier.isAbstract(ifcMethod.getModifiers())) { - if (result == null) { - result = new LinkedList(); - } - result.add(ifcMethod); - } - } - } - return result; - } - - /** - * Invoke the given callback on all fields in the target class, going up the - * class hierarchy to get all declared fields. - * @param clazz the target class to analyze - * @param fc the callback to invoke for each field - * @since 4.2 - * @see #doWithFields - */ - public static void doWithLocalFields(Class clazz, FieldCallback fc) { - for (Field field : getDeclaredFields(clazz)) { - try { - fc.doWith(field); - } - catch (IllegalAccessException ex) { - throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex); - } - } - } - - /** - * Invoke the given callback on all fields in the target class, going up the - * class hierarchy to get all declared fields. - * @param clazz the target class to analyze - * @param fc the callback to invoke for each field - */ - public static void doWithFields(Class clazz, FieldCallback fc) { - doWithFields(clazz, fc, null); - } - - /** - * Invoke the given callback on all fields in the target class, going up the - * class hierarchy to get all declared fields. - * @param clazz the target class to analyze - * @param fc the callback to invoke for each field - * @param ff the filter that determines the fields to apply the callback to - */ - public static void doWithFields(Class clazz, FieldCallback fc, FieldFilter ff) { - // Keep backing up the inheritance hierarchy. - Class targetClass = clazz; - do { - Field[] fields = getDeclaredFields(targetClass); - for (Field field : fields) { - if (ff != null && !ff.matches(field)) { - continue; - } - try { - fc.doWith(field); - } - catch (IllegalAccessException ex) { - throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex); - } - } - targetClass = targetClass.getSuperclass(); - } - while (targetClass != null && targetClass != Object.class); - } - - /** - * This variant retrieves {@link Class#getDeclaredFields()} from a local cache - * in order to avoid the JVM's SecurityManager check and defensive array copying. - * @param clazz the class to introspect - * @return the cached array of fields - * @see Class#getDeclaredFields() - */ - private static Field[] getDeclaredFields(Class clazz) { - Field[] result = null; - if (result == null) { - result = clazz.getDeclaredFields(); - } - return result; - } - - /** - * Given the source object and the destination, which must be the same class - * or a subclass, copy all fields, including inherited fields. Designed to - * work on objects with public no-arg constructors. - */ - public static void shallowCopyFieldState(final Object src, final Object dest) { - if (src == null) { - throw new IllegalArgumentException("Source for field copy cannot be null"); - } - if (dest == null) { - throw new IllegalArgumentException("Destination for field copy cannot be null"); - } - if (!src.getClass().isAssignableFrom(dest.getClass())) { - throw new IllegalArgumentException("Destination class [" + dest.getClass().getName() + - "] must be same or subclass as source class [" + src.getClass().getName() + "]"); - } - doWithFields(src.getClass(), new FieldCallback() { - @Override - public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { - makeAccessible(field); - Object srcValue = field.get(src); - field.set(dest, srcValue); - } - }, COPYABLE_FIELDS); - } - - - /** - * Action to take on each method. - */ - public interface MethodCallback { - - /** - * Perform an operation using the given method. - * @param method the method to operate on - */ - void doWith(Method method) throws IllegalArgumentException, IllegalAccessException; - } - - - /** - * Callback optionally used to filter methods to be operated on by a method callback. - */ - public interface MethodFilter { - - /** - * Determine whether the given method matches. - * @param method the method to check - */ - boolean matches(Method method); - } - - - /** - * Callback interface invoked on each field in the hierarchy. - */ - public interface FieldCallback { - - /** - * Perform an operation using the given field. - * @param field the field to operate on - */ - void doWith(Field field) throws IllegalArgumentException, IllegalAccessException; - } - - - /** - * Callback optionally used to filter fields to be operated on by a field callback. - */ - public interface FieldFilter { - - /** - * Determine whether the given field matches. - * @param field the field to check - */ - boolean matches(Field field); - } - - - /** - * Pre-built FieldFilter that matches all non-static, non-final fields. - */ - public static final FieldFilter COPYABLE_FIELDS = new FieldFilter() { - - @Override - public boolean matches(Field field) { - return !(Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())); - } - }; - - - /** - * Pre-built MethodFilter that matches all non-bridge methods. - */ - public static final MethodFilter NON_BRIDGED_METHODS = new MethodFilter() { - - @Override - public boolean matches(Method method) { - return !method.isBridge(); - } - }; - - - /** - * Pre-built MethodFilter that matches all non-bridge methods - * which are not declared on {@code java.lang.Object}. - */ - public static final MethodFilter USER_DECLARED_METHODS = new MethodFilter() { - - @Override - public boolean matches(Method method) { - return (!method.isBridge() && method.getDeclaringClass() != Object.class); - } - }; - -} diff --git a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/VerifyUtils.java b/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/VerifyUtils.java deleted file mode 100644 index 98eed71aa..000000000 --- a/bytekit/src/main/java/com/taobao/arthas/bytekit/utils/VerifyUtils.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; - -import com.alibaba.arthas.deps.org.objectweb.asm.ClassReader; -import com.alibaba.arthas.deps.org.objectweb.asm.ClassVisitor; -import com.alibaba.arthas.deps.org.objectweb.asm.ClassWriter; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.util.CheckClassAdapter; - -/** - * - * @author hengyunabc - * - */ -public class VerifyUtils { - - public static void asmVerify(byte[] bytes, boolean printResults) throws IOException { - ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); - ClassReader cr = new ClassReader(inputStream); - CheckClassAdapter.verify(cr, true, new PrintWriter(System.out)); - } - - public static void asmVerify(byte[] bytes) throws IOException { - ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); - ClassReader cr = new ClassReader(inputStream); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); - ClassVisitor cv = new CheckClassAdapter(cw); - - cr.accept(cv, 0); - } - - public static Object instanceVerity(byte[] bytes) throws Exception { - String name = Type.getObjectType(AsmUtils.toClassNode(bytes).name).getClassName(); - - @SuppressWarnings("resource") - ClassbyteClassLoader cl = new ClassbyteClassLoader(ClassLoaderUtils.getUrls(ClassLoader.getSystemClassLoader()), - ClassLoader.getSystemClassLoader().getParent()); - - cl.addClass(name, bytes); - - Class loadClass = cl.loadClass(name); - return loadClass.newInstance(); - } - - public static Object invoke(Object instance, String name, Object... args) throws Exception { - Method[] methods = instance.getClass().getMethods(); - for (Method method : methods) { - if (name.contentEquals(method.getName())) { - return method.invoke(instance, args); - } - } - throw new NoSuchMethodError("name: " + name); - } - - public static class ClassbyteClassLoader extends URLClassLoader { - public ClassbyteClassLoader(URL[] urls, ClassLoader cl) { - super(urls, cl); - } - - public Class addClass(String name, byte[] bytes) throws ClassFormatError { - Class cl = defineClass(name, bytes, 0, bytes.length); - resolveClass(cl); - - return cl; - } - } - -} diff --git a/bytekit/src/test/java/com/example/ByteKitDemo.java b/bytekit/src/test/java/com/example/ByteKitDemo.java deleted file mode 100644 index bd6139f00..000000000 --- a/bytekit/src/test/java/com/example/ByteKitDemo.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.example; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtEnter; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExceptionExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler; -import com.taobao.arthas.bytekit.asm.interceptor.parser.DefaultInterceptorClassParser; -import com.taobao.arthas.bytekit.utils.AgentUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.Decompiler; - -/** - * - * @author hengyunabc 2020-05-21 - * - */ -public class ByteKitDemo { - - public static class Sample { - private int exceptionCount = 0; - - public String hello(String str, boolean exception) { - if (exception) { - exceptionCount++; - throw new RuntimeException("test exception, str: " + str); - } - return "hello " + str; - } - } - - public static class PrintExceptionSuppressHandler { - - @ExceptionHandler(inline = true) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.out.println("exception handler: " + clazz); - e.printStackTrace(); - } - } - - public static class SampleInterceptor { - - @AtEnter(inline = true, suppress = RuntimeException.class, suppressHandler = PrintExceptionSuppressHandler.class) - public static void atEnter(@Binding.This Object object, - @Binding.Class Object clazz, - @Binding.Args Object[] args, - @Binding.MethodName String methodName, - @Binding.MethodDesc String methodDesc) { - System.out.println("atEnter, args[0]: " + args[0]); - } - - @AtExit(inline = true) - public static void atExit(@Binding.Return Object returnObject) { - System.out.println("atExit, returnObject: " + returnObject); - } - - @AtExceptionExit(inline = true, onException = RuntimeException.class) - public static void atExceptionExit(@Binding.Throwable RuntimeException ex, - @Binding.Field(name = "exceptionCount") int exceptionCount) { - System.out.println("atExceptionExit, ex: " + ex.getMessage() + ", field exceptionCount: " + exceptionCount); - } - } - - public static void main(String[] args) throws Exception { - AgentUtils.install(); - - // 启动Sample,不断执行 - final Sample sample = new Sample(); - Thread t = new Thread(new Runnable() { - @Override - public void run() { - for (int i = 0; i < 100; ++i) { - try { - TimeUnit.SECONDS.sleep(3); - String result = sample.hello("" + i, (i % 3) == 0); - System.out.println("call hello result: " + result); - } catch (Throwable e) { - // ignore - System.out.println("call hello exception: " + e.getMessage()); - } - } - } - }); - t.start(); - - // 解析定义的 Interceptor类 和相关的注解 - DefaultInterceptorClassParser interceptorClassParser = new DefaultInterceptorClassParser(); - List processors = interceptorClassParser.parse(SampleInterceptor.class); - - // 加载字节码 - ClassNode classNode = AsmUtils.loadClass(Sample.class); - - // 对加载到的字节码做增强处理 - for (MethodNode methodNode : classNode.methods) { - if (methodNode.name.equals("hello")) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode); - for (InterceptorProcessor interceptor : processors) { - interceptor.process(methodProcessor); - } - } - } - - // 获取增强后的字节码 - byte[] bytes = AsmUtils.toBytes(classNode); - - // 查看反编译结果 - System.out.println(Decompiler.decompile(bytes)); - - // 等待,查看未增强里的输出结果 - TimeUnit.SECONDS.sleep(10); - - // 通过 reTransform 增强类 - AgentUtils.reTransform(Sample.class, bytes); - System.in.read(); - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/TryCatchBlockTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/TryCatchBlockTest.java deleted file mode 100644 index ec34f6353..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/TryCatchBlockTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.taobao.arthas.bytekit.asm; - -import java.lang.instrument.Instrumentation; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.JumpInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.LabelNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.taobao.arthas.bytekit.utils.AsmOpUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.Decompiler; -import com.taobao.arthas.bytekit.utils.VerifyUtils; - -import net.bytebuddy.agent.ByteBuddyAgent; - -public class TryCatchBlockTest { - - static public class Hello { - - public long sss(String msg, int i, long l) { - return 124L; - } - - public long toBeCall(int i , long l, String s) { - return l + i; - } - -// public String say(String msg, int i, long l) { -// i = 0; -// System.out.println("hello"); -// i = 0; -// sss(msg, i, l); -// return ""; -// } - - public int say(int ii) { - toBeCall(ii, 123L, ""); - return 123; - } - } - - public static void ttt() throws Throwable { - try { - System.out.println(); - } catch (Throwable e) { - e.printStackTrace(); - throw e; - } - try { - System.out.println(); - } catch (Throwable e) { - e.printStackTrace(); - throw e; - } - } - - @Test - public void test() throws Exception { - - Instrumentation instrumentation = ByteBuddyAgent.install(); - - ClassNode classNode = AsmUtils.loadClass(Hello.class); - - List methods = AsmUtils.findMethods(classNode.methods, "say"); - - MethodNode methodNode = methods.get(0); - - AbstractInsnNode insnNode = methodNode.instructions.getFirst(); - - List methodInsnNodes = new ArrayList(); - - while (insnNode != null) { - if (insnNode instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - methodInsnNodes.add(methodInsnNode); - } - insnNode = insnNode.getNext(); - } - - for (MethodInsnNode methodInsnNode : methodInsnNodes) { - TryCatchBlock tryCatchBlock = new TryCatchBlock(methodNode); - - InsnList toInsert = new InsnList(); - - LabelNode gotoDest = new LabelNode(); - - LabelNode startLabelNode = tryCatchBlock.getStartLabelNode(); - LabelNode endLabelNode = tryCatchBlock.getEndLabelNode(); - - toInsert.add(new JumpInsnNode(Opcodes.GOTO, gotoDest)); - toInsert.add(endLabelNode); - - AsmOpUtils.dup(toInsert); - toInsert.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Type.getType(Throwable.class).getInternalName(), - "printStackTrace", "()V", false)); - - AsmOpUtils.throwException(toInsert); - - toInsert.add(gotoDest); - - methodNode.instructions.insertBefore(methodInsnNode, startLabelNode); - methodNode.instructions.insert(methodInsnNode, toInsert); - - tryCatchBlock.sort(); - } - - byte[] bytes = AsmUtils.toBytes(classNode); - - String decompile = Decompiler.decompile(bytes); - System.err.println(decompile); - - VerifyUtils.asmVerify(bytes, true); - - VerifyUtils.instanceVerity(bytes); - - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemo.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemo.java deleted file mode 100644 index 2daf425f5..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemo.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - -public class InstDemo { - - public int returnInt(int i) { - System.out.println(new Object[] { i }); - return 9998; - } - - public static void onEnter(Object[] args) { - System.out.println(args); - } - - public static int returnIntStatic(int i) { - return 9998; - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemoTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemoTest.java deleted file mode 100644 index 8dc26a9f1..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemoTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - -import java.util.List; - -import org.junit.Test; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AnnotationNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.FieldNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.Decompiler; -import com.taobao.arthas.bytekit.utils.VerifyUtils; - -public class InstDemoTest { - - @Test - public void test() throws Exception { - - ClassNode apmClassNode = AsmUtils.loadClass(InstDemo_APM.class); - - ClassNode originClassNode = AsmUtils.loadClass(InstDemo.class); - - ClassNode targetClassNode = AsmUtils.copy(originClassNode); - - - byte[] renameClass = AsmUtils.renameClass(AsmUtils.toBytes(apmClassNode), Type.getObjectType(originClassNode.name).getClassName()); - - apmClassNode = AsmUtils.toClassNode(renameClass); - - for(FieldNode fieldNode : apmClassNode.fields) { - if( fieldNode.visibleAnnotations != null) { - for( AnnotationNode annotationNode : fieldNode.visibleAnnotations) { - System.err.println(annotationNode.desc); - System.err.println(annotationNode.values); - - if(Type.getType(NewField.class).equals(Type.getType(annotationNode.desc))) { - AsmUtils.addField(targetClassNode, fieldNode); - } - - } - } - } - - for (MethodNode methodNode : apmClassNode.methods) { - methodNode = AsmUtils.removeLineNumbers(methodNode); - if (methodNode.name.startsWith("__origin_")) { - continue; - } else { - MethodNode findMethod = AsmUtils.findMethod(originClassNode.methods, methodNode); - if (findMethod != null) { - // 先要替换 invokeOrigin ,要判断 - // 从 apm 里查找 __origin_ 开头的函数,忽略 - // 查找 非 __origin_ 开头的函数,在原来的类里查找,如果有同样签名的函数 - // 则从函数里查找 是否有 __origin_ 的函数调用。如果有的话,则从原有的类里查找到 method,再inline掉。 - - List originMethodInsnNodes = AsmUtils.findMethodInsnNodeWithPrefix(methodNode, - "__origin_"); - - for (MethodInsnNode methodInsnNode : originMethodInsnNodes) { - String toInlineMethodName = methodInsnNode.name.substring("__origin_".length()); - MethodNode originMethodNode = AsmUtils.findMethod(originClassNode.methods, toInlineMethodName, - findMethod.desc); - - MethodNode tmpMethodNode = AsmUtils.copy(originMethodNode); - tmpMethodNode.name = methodInsnNode.name; - - MethodProcessor methodProcessor = new MethodProcessor(apmClassNode.name, methodNode); - methodProcessor.inline(originClassNode.name, tmpMethodNode); - - AsmUtils.replaceMethod(targetClassNode, methodProcessor.getMethodNode()); - - } - - } else { - // 没找到的函数,则加进去 - AsmUtils.addMethod(targetClassNode, methodNode); - } - } - - - } - - byte[] resutlBytes = AsmUtils.toBytes(targetClassNode); - - System.err.println(Decompiler.decompile(resutlBytes)); - - System.err.println(AsmUtils.toASMCode(resutlBytes)); - - VerifyUtils.asmVerify(resutlBytes); - VerifyUtils.instanceVerity(resutlBytes); - } -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemo_APM.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemo_APM.java deleted file mode 100644 index 75cfd3aed..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InstDemo_APM.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - -@Instrument -public class InstDemo_APM { - - @NewField - private String newField; - - public int newMethod(String s) { - return s.length() + 998; - } - - // 这种方式来写怎么样?有点丑,但是不需要写那些转换的代码。 在插件的编绎出结果后,可以检查下 名字,static,参数等是否匹配的。 - // 这种处理有点丑,但inline应该没问题 - public int __origin_returnInt(int i) { - return 0; - } - - public int returnInt(int i) { - - int re = __origin_returnInt(i); - - return 9998 + re; - } - - public static int returnIntStatic(int i) { - return 9998; - } -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginDemo.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginDemo.java deleted file mode 100644 index 041d26ea0..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginDemo.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - -import java.util.Date; - -/** - * @author hengyunabc 2019-03-13 - * - */ -public class InvokeOriginDemo { - - public void returnVoid() { - } - - public Void returnVoidObject() { - int i = 0; - try { - int parseInt = Integer.parseInt("1000"); - i += parseInt; - } catch (Exception e) { - System.err.println(i + " " + e); - } - - return null; - } - - public int returnInt(int i) { - return 9998; - } - - public int returnIntToObject(int i) { - - return 9998; - } - - public int returnIntToInteger(int i) { - - return 9998; - } - - public static int returnIntStatic(int i) { - return 9998; - } - - public long returnLong() { - return 9998L; - } - - public long returnLongToObject() { - return 9998L; - } - - public String[] returnStrArray() { - String[] result = new String[] {"abc", "xyz" , "ufo"}; - return result; - } - - public String[] returnStrArrayWithArgs(int i, String s, long l) { - String[] result = new String[] {"abc" + i, "xyz" + s , "ufo" + l}; - return result; - } - - public String returnStr() { - return new Date().toString(); - } - - public Object returnObject() { - return InvokeOriginDemo.class; - } - - - public int recursive(int i) { - if (i == 1) { - return 1; - } - return i + recursive(i - 1); - } -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginDemo_APM.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginDemo_APM.java deleted file mode 100644 index a5d41a27d..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginDemo_APM.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - -/** - * - * @author hengyunabc 2019-03-18 - * - */ -public class InvokeOriginDemo_APM { - - public void returnVoid() { - Object o = InstrumentApi.invokeOrigin(); - System.out.println(o); - } - - public Void returnVoidObject() { - Void v = InstrumentApi.invokeOrigin(); - System.out.println(v); - return v; - } - - public int returnInt(int i) { - System.out.println("before"); - int value = InstrumentApi.invokeOrigin(); - System.out.println("after"); - return value + 123; - } - - public int returnIntToObject(int i) { - Object value = InstrumentApi.invokeOrigin(); - return 9998 + (Integer) value; - } - - public int returnIntToInteger(int i) { - - Integer ixx = InstrumentApi.invokeOrigin(); - - return ixx + 9998; - } - - public static int returnIntStatic(int i) { - int result = InstrumentApi.invokeOrigin(); - return 9998 + result; - } - - public long returnLong() { - long result = InstrumentApi.invokeOrigin(); - return 9998L + result; - } - - public long returnLongToObject() { - Long lll = InstrumentApi.invokeOrigin(); - return 9998L + lll; - } - - public String[] returnStrArray() { - String[] result = InstrumentApi.invokeOrigin(); - System.err.println(result); - return result; - } - - public String[] returnStrArrayWithArgs(int i, String s, long l) { - System.out.println(i); - String[] result = InstrumentApi.invokeOrigin(); - result[0] = "fff"; - return result; - } - - public String returnStr() { - System.err.println("ssss"); - Object result = InstrumentApi.invokeOrigin(); - return "hello" + result; - } - - public Object returnObject() { - InstrumentApi.invokeOrigin(); - return InvokeOriginDemo.class; - } - - public int recursive(int i) { - int result = InstrumentApi.invokeOrigin(); - - System.err.println(result); - return result; - } -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginTest.java deleted file mode 100644 index 4410b1a31..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/inst/InvokeOriginTest.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.taobao.arthas.bytekit.asm.inst; - -import java.io.IOException; - -import org.assertj.core.api.Assertions; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; - -import com.taobao.arthas.bytekit.asm.inst.impl.InstrumentImpl; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.Decompiler; -import com.taobao.arthas.bytekit.utils.VerifyUtils; - -/** - * - * @author hengyunabc 2019-03-18 - * - */ -public class InvokeOriginTest { - - ClassNode apmClassNode; - ClassNode originClassNode; - - ClassNode targetClassNode; - - @Rule - public TestName testName = new TestName(); - - @BeforeClass - public static void beforeClass() throws IOException { - - } - - @Before - public void before() throws IOException { - apmClassNode = AsmUtils.loadClass(InvokeOriginDemo_APM.class); - originClassNode = AsmUtils.loadClass(InvokeOriginDemo.class); - - byte[] renameClass = AsmUtils.renameClass(AsmUtils.toBytes(apmClassNode), - Type.getObjectType(originClassNode.name).getClassName()); - - apmClassNode = AsmUtils.toClassNode(renameClass); - - targetClassNode = AsmUtils.copy(originClassNode); - } - - private Object replace(String methodName) throws Exception { - System.err.println(methodName); - for (MethodNode methodNode : apmClassNode.methods) { - if (methodNode.name.equals(methodName)) { - methodNode = AsmUtils.removeLineNumbers(methodNode); - // 从原来的类里查找对应的函数 - MethodNode findMethod = AsmUtils.findMethod(originClassNode.methods, methodNode); - if (findMethod != null) { - MethodNode methodNode2 = InstrumentImpl.replaceInvokeOrigin(originClassNode.name, findMethod, - methodNode); - - System.err.println(Decompiler.toString(methodNode2)); - - AsmUtils.replaceMethod(targetClassNode, methodNode2); - - } else { - - } - } - } - - byte[] resutlBytes = AsmUtils.toBytes(targetClassNode); - - System.err.println("================="); - - System.err.println(Decompiler.decompile(resutlBytes)); - - // System.err.println(AsmUtils.toASMCode(resutlBytes)); - - VerifyUtils.asmVerify(resutlBytes); - return VerifyUtils.instanceVerity(resutlBytes); - } - - @Test - public void test_returnVoid() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - - Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(null); - } - - @Test - public void test_returnVoidObject() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(null); - } - - @Test - public void test_returnInt() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123)).isEqualTo(9998 + 123); - } - - @Test - public void test_returnIntToObject() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123)).isEqualTo(9998 + 9998); - } - - @Test - public void test_returnIntToInteger() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123)).isEqualTo(9998 + 9998); - } - - @Test - public void test_returnIntStatic() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123)).isEqualTo(9998 + 9998); - } - - @Test - public void test_returnLong() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(9998L + 9998); - } - - @Test - public void test_returnLongToObject() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(9998L + 9998); - } - - @Test - public void test_returnStrArray() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(new String[] { "abc", "xyz", "ufo" }); - } - - @Test - public void test_returnStrArrayWithArgs() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123, "sss", 777L)) - .isEqualTo(new Object[] { "fff", "xyz" + "sss", "ufo" + 777 }); - } - - @Test - public void test_returnStr() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName)).asString().startsWith("hello"); - } - - @Test - public void test_returnObject() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(object.getClass()); - } - - @Test - public void test_recursive() throws Exception { - String methodName = testName.getMethodName().substring("test_".length()); - Object object = replace(methodName); - Assertions.assertThat(VerifyUtils.invoke(object, methodName, 100)).isEqualTo((100 + 1) * 100 / 2); - } -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtEnterTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtEnterTest.java deleted file mode 100644 index a90dc7177..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtEnterTest.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtEnter; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtEnterTest { - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Rule - public OutputCapture capture = new OutputCapture(); - - public static class Sample { - - long longField; - String strField; - static int intField; - - public int hello(String str, boolean exception) { - if (exception) { - throw new RuntimeException("test exception"); - } - return str.length(); - } - - public long toBeInvoke(int i , long l, String s, long ll) { - return l + ll; - } - - public void testInvokeArgs() { - toBeInvoke(1, 123L, "abc", 100L); - } - - } - - public static class TestPrintSuppressHandler { - - @ExceptionHandler(inline = true) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.err.println("exception handler: " + clazz); - e.printStackTrace(); - } - } - - public static class EnterInterceptor { - - @AtEnter(inline = true - , suppress = RuntimeException.class, suppressHandler = TestPrintSuppressHandler.class - ) - public static long onEnter( - @Binding.This Object object, @Binding.Class Object clazz, - @Binding.Field(name = "longField") long longField, - @Binding.Field(name = "longField") Object longFieldObject, - @Binding.Field(name = "intField") int intField, - @Binding.Field(name = "strField") String strField, - @Binding.Field(name = "intField") Object intFielObject, - @Binding.MethodName String methodName, - @Binding.MethodDesc String methodDesc - ) { - System.err.println("onEnter, object:" + object); - System.err.println("onEnter, methodName:" + methodName); - System.err.println("onEnter, methodDesc:" + methodDesc); - return 123L; - } - - } - - - - @Test - public void testEnter() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(EnterInterceptor.class).methodMatcher("hello") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - new Sample().hello("abc", false); - - System.err.println(Decompiler.decompile(bytes)); - - assertThat(capture.toString()).contains("onEnter, object:"); - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtExceptionExitTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtExceptionExitTest.java deleted file mode 100644 index 323e85863..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtExceptionExitTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExceptionExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtExceptionExitTest { - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Rule - public OutputCapture capture = new OutputCapture(); - - public static class Sample { - - long longField; - String strField; - static int intField; - - public int hello(String str, boolean exception) { - if (exception) { - throw new RuntimeException("test exception"); - } - return str.length(); - } - - public long toBeInvoke(int i , long l, String s, long ll) { - return l + ll; - } - - public void testInvokeArgs() { - toBeInvoke(1, 123L, "abc", 100L); - } - - } - - public static class TestPrintSuppressHandler { - - @ExceptionHandler(inline = true) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.err.println("exception handler: " + clazz); - System.err.println(e.getMessage()); - assertThat(e).hasMessage("exception for ExceptionHandler"); - } - } - - public static class ExceptionExitInterceptor { - @AtExceptionExit(inline = false, onException = RuntimeException.class ,suppress = Throwable.class, suppressHandler = TestPrintSuppressHandler.class) - public static void onExceptionExit(@Binding.Throwable RuntimeException ex, @Binding.This Object object, - @Binding.Class Object clazz) { - System.err.println("AtExceptionExit, ex:" + ex); - throw new RuntimeException("exception for ExceptionHandler"); - } - } - - - @Test - public void testExecptionExitException() throws Exception { - - TestHelper helper = TestHelper.builder().interceptorClass(ExceptionExitInterceptor.class).methodMatcher("hello") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - System.err.println(Decompiler.decompile(bytes)); - try { - new Sample().hello("abc", true); - } catch (Exception e) { - assertThat(e).isInstanceOf(RuntimeException.class).hasMessageContaining("test exception"); - } - - assertThat(capture.toString()).contains("AtExceptionExit, ex:"); - - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtExitTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtExitTest.java deleted file mode 100644 index 1462500ad..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtExitTest.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Rule; -import org.junit.Test; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtExitTest { - @Rule - public OutputCapture capture = new OutputCapture(); - - static class Sample { - long longField; - int intField; - String strField; - - public void voidExit() { - - } - - public long longExit() { - return 100L; - } - - public static long staticExit() { - return 999L; - } - } - - public static class TestPrintSuppressHandler { - - @ExceptionHandler(inline = false) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.err.println("exception handler: " + clazz); - e.printStackTrace(); - } - } - - public static class TestAccessInterceptor { - @AtExit(inline = false) - public static void atExit(@Binding.This Object object, - @Binding.Class Object clazz - , - @Binding.Return Object re - ) { - System.err.println("AtFieldAccess: this" + object); - } - } - - public static class ChangeReturnInterceptor { - - @AtExit(inline = false, suppress = RuntimeException.class, suppressHandler = TestPrintSuppressHandler.class) - public static Object onExit(@Binding.This Object object, @Binding.Class Object clazz) { - System.err.println("onExit, object:" + object); - return 123L; - } - } - - @Test - public void testExit() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(TestAccessInterceptor.class).methodMatcher("voidExit") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - new Sample().voidExit(); - - System.err.println(Decompiler.decompile(bytes)); - - assertThat(capture.toString()).contains("AtFieldAccess: this"); - } - - - @Test - public void testExitAndChangeReturn() throws Exception { - - TestHelper helper = TestHelper.builder().interceptorClass(ChangeReturnInterceptor.class).methodMatcher("longExit") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - System.err.println(Decompiler.decompile(bytes)); - - long re = new Sample().longExit(); - - assertThat(re).isEqualTo(123); - assertThat(capture.toString()).contains("onExit, object:"); - } -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtFieldAccessTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtFieldAccessTest.java deleted file mode 100644 index 45024ce2d..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtFieldAccessTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Rule; -import org.junit.Test; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtFieldAccess; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtFieldAccessTest { - @Rule - public OutputCapture capture = new OutputCapture(); - - class Sample { - long longField; - int intField; - String strField; - - public int testReadField(int ii) { - longField = 999; - return 123; - } - } - - public static class TestPrintSuppressHandler { - - @ExceptionHandler(inline = false) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.err.println("exception handler: " + clazz); - e.printStackTrace(); - } - } - - public static class FieldAccessInterceptor { - @AtFieldAccess(name = "longField" , inline =false) - public static void onFieldAccess(@Binding.This Object object, - @Binding.Class Object clazz) { - System.err.println("AtFieldAccess: this" + object); - } - } - - @Test - public void testEnter() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(FieldAccessInterceptor.class).methodMatcher("testReadField") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - new Sample().testReadField(100); - - System.err.println(Decompiler.decompile(bytes)); - - assertThat(capture.toString()).contains("AtFieldAccess: this"); - } - - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtInvokeTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtInvokeTest.java deleted file mode 100644 index f6c565829..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtInvokeTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Rule; -import org.junit.Test; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtInvoke; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtInvokeTest { - @Rule - public OutputCapture capture = new OutputCapture(); - - static class Sample { - long longField; - int intField; - String strField; - - public Sample(int i, long l, String s) { - staticToBeCall(i, l, s); - aaa("aaa"); - } - - public int testCall(int ii) { - toBeCall(ii, 123L, ""); - System.err.println("abc"); - - aaa("abc"); - return 123; - } - - - public void aaa(String aaa) { - return ; - } - - public long toBeCall(int i , long l, String s) { - return l + i; - } - - public static long staticToBeCall(int i , long l, String s) { - return l + i; - } - } - - public static class TestPrintSuppressHandler { - - @ExceptionHandler(inline = false) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.err.println("exception handler: " + clazz); - e.printStackTrace(); - } - } - - public static class TestAccessInterceptor { - @AtInvoke(name = "", inline = false, whenComplete=false, excludes = {"System."}) - public static void onInvoke( - @Binding.This Object object, - @Binding.Class Object clazz - , - @Binding.Line int line, - @Binding.InvokeArgs Object[] args - ) { - System.err.println("onInvoke: line: " + line); - System.err.println("onInvoke: this: " + object); - } - - @AtInvoke(name = "toBeCall", inline = false, whenComplete = true) - public static void onInvokeAfter( - @Binding.This Object object, - @Binding.Class Object clazz - , - @Binding.InvokeReturn Object invokeReturn - , - @Binding.InvokeMethodDeclaration String declaration - ) { - System.err.println("onInvokeAfter: this" + object); - System.err.println("declaration: " + declaration); - assertThat(declaration).isEqualTo("long toBeCall(int, long, java.lang.String)"); - - System.err.println("invokeReturn: " + invokeReturn); - assertThat(invokeReturn).isEqualTo(100 + 123L); - } - } - - //@Test - // TODO fix com.taobao.arthas.bytekit.asm.location.Location.InvokeLocation satck save - public void testInvokeBefore() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(TestAccessInterceptor.class).methodMatcher("testCall") - .redefine(true); - byte[] bytes = helper.process(Sample.class); - - new Sample(100, 100L, "").testCall(100); - - System.err.println(Decompiler.decompile(bytes)); - - assertThat(capture.toString()).contains("onInvoke: this"); - } - - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtLineTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtLineTest.java deleted file mode 100644 index 2bcba1672..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtLineTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Arrays; - -import org.junit.Rule; -import org.junit.Test; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtLine; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtLineTest { - @Rule - public OutputCapture capture = new OutputCapture(); - - static class Sample { - - public int testLine(int i) { - String s = "" + i; - if(i > 0) { - String abc = s + i; - i++; - i = i * 100 - + i - - 100 + Math.max(100, i); - i += s.length() + abc.length(); - }else { - if(i == -1) { - try { - System.err.println("i is -1"); - throw new RuntimeException(); - } catch (Exception e) { - System.err.println(e.getMessage()); - } - - } - } - return i * 2; - } - - } - - public static class TestAccessInterceptor { - - @AtLine(lines = { -1}, inline = false) - public static void atLine( - @Binding.This Object object, - @Binding.Class Object clazz - , - @Binding.Line int line, - @Binding.Args Object[] args - , - @Binding.ArgNames String[] argNames - , - @Binding.LocalVars Object[] vars, - @Binding.LocalVarNames String[] varNames - ) { - System.err.println("atLine: this" + object); - System.err.println("line: " + line); - System.err.println("args: " + Arrays.toString(args)); - System.err.println("argNames: " + Arrays.toString(argNames)); - - System.err.println("vars: " + Arrays.toString(vars)); - System.err.println("varNames: " + Arrays.toString(varNames)); - } - } - - @Test - public void testLine() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(TestAccessInterceptor.class).methodMatcher("*") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - new Sample().testLine(100); - - System.err.println(Decompiler.decompile(bytes)); - - assertThat(capture.toString()).contains("atLine: this"); - } - - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtSyncEnterTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtSyncEnterTest.java deleted file mode 100644 index 91ccbb512..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtSyncEnterTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Arrays; - -import org.junit.Rule; -import org.junit.Test; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtSyncEnter; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtSyncEnterTest { - @Rule - public OutputCapture capture = new OutputCapture(); - - static class Sample { - - public int testLine(int i) { - String s = "" + i; - synchronized (s) { - if(i > 0) { - String abc = s + i; - i++; - i = i * 100 - + i - - 100 + Math.max(100, i); - i += s.length() + abc.length(); - }else { - if(i == -1) { - try { - System.err.println("i is -1"); - throw new RuntimeException(); - } catch (Exception e) { - System.err.println(e.getMessage()); - } - - } - } - } - - return i * 2; - } - - } - - public static class TestInterceptor { - - @AtSyncEnter(whenComplete=false, inline = false) - public static void atSyncEnter( - @Binding.This Object object, - @Binding.Class Object clazz - , - @Binding.Args Object[] args - , - @Binding.ArgNames String[] argNames - , - @Binding.LocalVars Object[] vars, - @Binding.LocalVarNames String[] varNames - , - @Binding.Monitor Object monitor - ) { - System.err.println("atSyncEnter: this" + object); - System.err.println("args: " + Arrays.toString(args)); - System.err.println("argNames: " + Arrays.toString(argNames)); - - System.err.println("vars: " + Arrays.toString(vars)); - System.err.println("varNames: " + Arrays.toString(varNames)); - - } - } - - @Test - public void test() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(TestInterceptor.class).methodMatcher("*") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - new Sample().testLine(100); - - System.err.println(Decompiler.decompile(bytes)); - - assertThat(capture.toString()).contains("atSyncEnter: this"); - } - - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtSyncExitTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtSyncExitTest.java deleted file mode 100644 index 9aef147d4..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtSyncExitTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Arrays; - -import org.junit.Rule; -import org.junit.Test; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtSyncExit; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtSyncExitTest { - @Rule - public OutputCapture capture = new OutputCapture(); - - static class Sample { - - public int testLine(int i) { - String s = "" + i; - synchronized (s) { - if(i > 0) { - String abc = s + i; - i++; - i = i * 100 - + i - - 100 + Math.max(100, i); - i += s.length() + abc.length(); - }else { - if(i == -1) { - try { - System.err.println("i is -1"); - throw new RuntimeException(); - } catch (Exception e) { - System.err.println(e.getMessage()); - } - - } - } - } - - return i * 2; - } - - } - - public static class TestInterceptor { - - @AtSyncExit(whenComplete=false, inline = false) - public static void atSyncExit( - @Binding.This Object object, - @Binding.Class Object clazz - , - @Binding.Args Object[] args - , - @Binding.ArgNames String[] argNames - , - @Binding.LocalVars Object[] vars, - @Binding.LocalVarNames String[] varNames - , - @Binding.Monitor Object monitor - ) { - System.err.println("atSyncExit: this" + object); - System.err.println("args: " + Arrays.toString(args)); - System.err.println("argNames: " + Arrays.toString(argNames)); - - System.err.println("vars: " + Arrays.toString(vars)); - System.err.println("varNames: " + Arrays.toString(varNames)); - - } - } - - @Test - public void test() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(TestInterceptor.class).methodMatcher("*") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - new Sample().testLine(100); - - System.err.println(Decompiler.decompile(bytes)); - - assertThat(capture.toString()).contains("atSyncExit: this"); - } - - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtThrowTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtThrowTest.java deleted file mode 100644 index d696ca978..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/AtThrowTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Arrays; - -import org.junit.Rule; -import org.junit.Test; -import org.springframework.boot.test.rule.OutputCapture; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtThrow; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler; -import com.taobao.arthas.bytekit.utils.Decompiler; - -public class AtThrowTest { - @Rule - public OutputCapture capture = new OutputCapture(); - - static class Sample { - - public static long testThrow(int i , long l, String s) { - try { - if(i < 0) { - throw new RuntimeException("eeeee"); - } - } catch (Exception e) { - - System.err.println(e.getMessage()); - } - return l + i; - } - } - - public static class TestPrintSuppressHandler { - - @ExceptionHandler(inline = false) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.err.println("exception handler: " + clazz); - e.printStackTrace(); - } - } - - public static class TestAccessInterceptor { - - @AtThrow(inline = false) - public static void atThrow( - @Binding.This Object object, - @Binding.Class Object clazz - , - @Binding.LocalVars Object[] vars, - @Binding.Throwable Throwable t - ) { - System.err.println("atThrow: this" + object); - System.err.println("vars: " + Arrays.toString(vars)); - System.err.println("t: " + t); - - assertThat(t).hasMessage("eeeee"); - } - } - - @Test - public void testThrow() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(TestAccessInterceptor.class).methodMatcher("testThrow") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - Sample.testThrow(-1, 0, null); - - System.err.println(Decompiler.decompile(bytes)); - - assertThat(capture.toString()).contains("atThrow: this"); - } - - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/InlineWhileTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/InlineWhileTest.java deleted file mode 100644 index 0175799b5..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/InlineWhileTest.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtEnter; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExceptionExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler; -import com.taobao.arthas.bytekit.utils.Decompiler; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.springframework.boot.test.rule.OutputCapture; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * testcase for IINC - */ -public class InlineWhileTest { - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Rule - public OutputCapture capture = new OutputCapture(); - - public static class Sample { - - public int hello(String str, boolean exception) { - if (exception) { - throw new RuntimeException("test exception"); - } - return str.length(); - } - } - - public static class TestPrintSuppressHandler { - - @ExceptionHandler(inline = true) - public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) { - System.err.println("exception handler: " + clazz); - e.printStackTrace(); - } - } - - public static class EnterInterceptor { - - @AtEnter(inline = true, - suppress = RuntimeException.class, - suppressHandler = TestPrintSuppressHandler.class - ) - public static long onEnter( - @Binding.This Object object, @Binding.Class Object clazz, - @Binding.MethodName String methodName, - @Binding.MethodDesc String methodDesc - ) { - System.err.println("onEnter, object:" + object); - System.err.println("onEnter, methodName:" + methodName); - System.err.println("onEnter, methodDesc:" + methodDesc); - - int i=0; - while (i++ < 3) { - System.err.println("enter: "+i); - } - return 123L; - } - - @AtExit(inline = true, - suppress = RuntimeException.class, - suppressHandler = TestPrintSuppressHandler.class - ) - public static void onExit( - @Binding.This Object object, @Binding.Class Object clazz, - @Binding.MethodName String methodName, - @Binding.MethodDesc String methodDesc - ) { - System.err.println("onExit, object:" + object); - System.err.println("onExit, methodName:" + methodName); - System.err.println("onExit, methodDesc:" + methodDesc); - - int i=0; - while (i++ < 3) { - System.err.println("exit: "+i); - } - } - - @AtExceptionExit - public static void onException(@Binding.This Object object, @Binding.Class Object clazz, - @Binding.MethodName String methodName, - @Binding.MethodDesc String methodDesc, - @Binding.Throwable Throwable ex) { - System.err.println("onException: "+ex); - int i=0; - i+=3; - System.err.println("exception: "+i); - } - } - - - - @Test - public void test1() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(EnterInterceptor.class).methodMatcher("hello") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - System.err.println(Decompiler.decompile(bytes)); - - new Sample().hello("abc", false); - - String actual = capture.toString(); - assertThat(actual).contains("onEnter, object:"); - assertThat(actual).contains("enter: 3"); - assertThat(actual).contains("onExit, object:"); - assertThat(actual).contains("exit: 3"); - - - } - - @Test - public void test2() throws Exception { - TestHelper helper = TestHelper.builder().interceptorClass(EnterInterceptor.class).methodMatcher("hello") - .reTransform(true); - byte[] bytes = helper.process(Sample.class); - - System.err.println(Decompiler.decompile(bytes)); - - try { - new Sample().hello("abc", true); - } catch (Exception e) { - e.printStackTrace(); - } - - String actual = capture.toString(); - assertThat(actual).contains("onEnter, object:"); - assertThat(actual).contains("enter: 3"); - assertThat(actual).contains("onException: java.lang.RuntimeException: test exception"); - assertThat(actual).contains("exception: 3"); - - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/TestHelper.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/TestHelper.java deleted file mode 100644 index aff87158b..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/interceptor/TestHelper.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.taobao.arthas.bytekit.asm.interceptor; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; - -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.parser.DefaultInterceptorClassParser; -import com.taobao.arthas.bytekit.utils.AgentUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.MatchUtils; -import com.taobao.arthas.bytekit.utils.VerifyUtils; - -/** - * - * @author hengyunabc - * - */ -public class TestHelper { - - private Class interceptorClass; - - private boolean redefine; - - private boolean reTransform; - - private String methodMatcher = "*"; - - private boolean asmVerity = true; - - public static TestHelper builder() { - return new TestHelper(); - } - - public TestHelper interceptorClass(Class interceptorClass) { - this.interceptorClass = interceptorClass; - return this; - } - - public TestHelper redefine(boolean redefine) { - this.redefine = redefine; - return this; - } - - public TestHelper reTransform(boolean reTransform) { - this.reTransform = reTransform; - return this; - } - - public TestHelper methodMatcher(String methodMatcher) { - this.methodMatcher = methodMatcher; - return this; - } - - public byte[] process(Class transform) throws Exception { - DefaultInterceptorClassParser defaultInterceptorClassParser = new DefaultInterceptorClassParser(); - - List interceptorProcessors = defaultInterceptorClassParser.parse(interceptorClass); - - ClassNode classNode = AsmUtils.loadClass(transform); - - List matchedMethods = new ArrayList(); - for (MethodNode methodNode : classNode.methods) { - if (MatchUtils.wildcardMatch(methodNode.name, methodMatcher)) { - matchedMethods.add(methodNode); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - byte[] bytes = AsmUtils.toBytes(classNode); - if (asmVerity) { - VerifyUtils.asmVerify(bytes); - } - - if (redefine) { - AgentUtils.redefine(transform, bytes); - } - - if (reTransform) { - AgentUtils.reTransform(transform, bytes); - } - - return bytes; - } -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/GroupFilterTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/GroupFilterTest.java deleted file mode 100644 index 9aa9cae02..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/GroupFilterTest.java +++ /dev/null @@ -1,318 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location.filter; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtEnter; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExceptionExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtInvoke; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtInvokeException; -import com.taobao.arthas.bytekit.asm.interceptor.parser.DefaultInterceptorClassParser; -import com.taobao.arthas.bytekit.asm.location.LocationType; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.Decompiler; -import com.taobao.arthas.bytekit.utils.MatchUtils; -import com.taobao.arthas.bytekit.utils.VerifyUtils; - -/** - * - * @author hengyunabc 2020-05-04 - * - */ -public class GroupFilterTest { - - public static class SpyInterceptor { - - @AtEnter(inline = true) - public static void atEnter(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.MethodName String methodName, @Binding.MethodDesc String methodDesc, - @Binding.Args Object[] args) { - SpyAPI.atEnter(clazz, methodName, methodDesc, target, args); - } - - @AtExit(inline = true) - public static void atExit(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.MethodName String methodName, @Binding.MethodDesc String methodDesc, - @Binding.Args Object[] args, @Binding.Return Object returnObj) { - SpyAPI.atExit(clazz, methodName, methodDesc, target, args, returnObj); - } - - @AtExceptionExit(inline = true) - public static void atExceptionExit(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.MethodName String methodName, @Binding.MethodDesc String methodDesc, - @Binding.Args Object[] args, @Binding.Throwable Throwable throwable) { - SpyAPI.atExceptionExit(clazz, methodName, methodDesc, target, args, throwable); - } - } - - public static class SpyTraceInterceptor { - @AtInvoke(name = "", inline = true, whenComplete = false, excludes = { "java.**", "**SpyAPI**" }) - public static void onInvoke(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeInfo String invokeInfo) { - SpyAPI.atBeforeInvoke(clazz, invokeInfo, target); - } - - @AtInvoke(name = "", inline = true, whenComplete = true, excludes = { "java.**", "**SpyAPI**" }) - public static void onInvokeAfter(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeInfo String invokeInfo) { - SpyAPI.atAfterInvoke(clazz, invokeInfo, target); - } - - @AtInvokeException(name = "", inline = true, excludes = { "java.**", "**SpyAPI**" }) - public static void onInvokeException(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeInfo String invokeInfo, @Binding.Throwable Throwable throwable) { - SpyAPI.atInvokeException(clazz, invokeInfo, target, throwable); - } - } - - public static class SpyTraceInterceptor2 { - @AtInvoke(name = "", inline = true, whenComplete = false, excludes = { "**SpyAPI**" }) - public static void onInvoke(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeInfo String invokeInfo) { - - SpyAPI.atBeforeInvoke(clazz, invokeInfo, target); - } - - @AtInvoke(name = "", inline = true, whenComplete = true, excludes = { "**SpyAPI**" }) - public static void onInvokeAfter(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeInfo String invokeInfo) { - SpyAPI.atAfterInvoke(clazz, invokeInfo, target); - } - - @AtInvokeException(name = "", inline = true, excludes = { "**SpyAPI**" }) - public static void onInvokeException(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeInfo String invokeInfo, @Binding.Throwable Throwable throwable) { - SpyAPI.atInvokeException(clazz, invokeInfo, target, throwable); - } - } - - public static class SpyAPI { - public static void atEnter(Class clazz, String methodName, String methodDesc, Object target, Object[] args) { - - } - - public static void atExceptionExit(Class clazz, String methodName, String methodDesc, Object target, - Object[] args, Throwable throwable) { - - } - - public static void atExit(Class clazz, String methodName, String methodDesc, Object target, Object[] args, - Object returnObj) { - - } - - public static void atBeforeInvoke(Class clazz, String invokeInfo, - Object target) { - - } - - public static void atInvokeException(Class clazz, String invokeInfo, - Object target, Throwable throwable) { - - } - - public static void atAfterInvoke(Class clazz, String invokeInfo, - Object target) { - - } - - } - - public static class TestAAA { - - int i = 0; - long l = 0; - - public TestAAA() { - xxx(1, 134L); - } - - public String hello(String str) { - - String result = ""; - - xxx(i, l); - - return result; - - } - - public String xxx(int i, long l) { - return "" + i + l; - } - - } - - @Test - public void test() throws Exception { - boolean skipJDKTrace = false; - - DefaultInterceptorClassParser defaultInterceptorClassParser = new DefaultInterceptorClassParser(); - - List interceptorProcessors = defaultInterceptorClassParser - .parse(SpyInterceptor.class); - - Class spyTraceInterceptorClass = SpyTraceInterceptor2.class; - if (skipJDKTrace == false) { - spyTraceInterceptorClass = SpyTraceInterceptor.class; - } - List traceInvokeProcessors = defaultInterceptorClassParser - .parse(spyTraceInterceptorClass); - interceptorProcessors.addAll(traceInvokeProcessors); - - - ClassNode classNode = AsmUtils.loadClass(TestAAA.class); - - List matchedMethods = new ArrayList(); - for (MethodNode methodNode : classNode.methods) { - if (MatchUtils.wildcardMatch(methodNode.name, "*")) { - matchedMethods.add(methodNode); - } - } - - GroupLocationFilter groupLocationFilter = new GroupLocationFilter(); - - LocationFilter enterFilter = new InvokeContainLocationFilter(Type.getInternalName(SpyAPI.class), "atEnter", - LocationType.ENTER); - LocationFilter existFilter = new InvokeContainLocationFilter(Type.getInternalName(SpyAPI.class), "atExit", - LocationType.EXIT); - LocationFilter exceptionFilter = new InvokeContainLocationFilter(Type.getInternalName(SpyAPI.class), - "atExceptionExit", LocationType.EXCEPTION_EXIT); - - groupLocationFilter.addFilter(enterFilter); - groupLocationFilter.addFilter(existFilter); - groupLocationFilter.addFilter(exceptionFilter); - - LocationFilter invokeBeforeFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), "atBeforeInvoke", - LocationType.INVOKE); - LocationFilter invokeAfterFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), - "atInvokeException", LocationType.INVOKE_COMPLETED); - LocationFilter invokeExceptionFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), - "atInvokeException", LocationType.INVOKE_EXCEPTION_EXIT); - groupLocationFilter.addFilter(invokeBeforeFilter); - groupLocationFilter.addFilter(invokeAfterFilter); - groupLocationFilter.addFilter(invokeExceptionFilter); - - - for(int i = 0 ; i < 20 ; ++i) { - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - } - - - byte[] bytes = AsmUtils.toBytes(classNode); - VerifyUtils.asmVerify(bytes); - - VerifyUtils.instanceVerity(bytes); - - System.out.println(Decompiler.decompile(bytes)); - - ClassNode classNode2 = AsmUtils.toClassNode(bytes); - for (MethodNode methodNode : classNode2.methods) { - if (!methodNode.name.equals("xxx")) { - System.err.println("method name: " + methodNode.name); - Assertions.assertThat( - AsmUtils.findMethodInsnNode(methodNode, Type.getInternalName(SpyAPI.class), "atBeforeInvoke")) - .size().isEqualTo(1); - } - } - - } - - @Test - public void test2() throws Exception { - - DefaultInterceptorClassParser defaultInterceptorClassParser = new DefaultInterceptorClassParser(); - - List interceptorProcessors = defaultInterceptorClassParser - .parse(SpyTraceInterceptor2.class); - - ClassNode classNode = AsmUtils.loadClass(TestAAA.class); - - List matchedMethods = new ArrayList(); - for (MethodNode methodNode : classNode.methods) { - if (MatchUtils.wildcardMatch(methodNode.name, "*")) { - matchedMethods.add(methodNode); - } - } - - LocationFilter enterFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), "atBeforeInvoke", - LocationType.INVOKE); - LocationFilter existFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), - "atInvokeException", LocationType.INVOKE_COMPLETED); - LocationFilter exceptionFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), - "atInvokeException", LocationType.INVOKE_EXCEPTION_EXIT); - GroupLocationFilter groupLocationFilter = new GroupLocationFilter(); - groupLocationFilter.addFilter(enterFilter); - groupLocationFilter.addFilter(existFilter); - groupLocationFilter.addFilter(exceptionFilter); - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - byte[] bytes = AsmUtils.toBytes(classNode); - VerifyUtils.asmVerify(bytes); - - VerifyUtils.instanceVerity(bytes); - - System.out.println(Decompiler.decompile(bytes)); - - ClassNode classNode2 = AsmUtils.toClassNode(bytes); - for (MethodNode methodNode : classNode2.methods) { - if (!methodNode.name.equals("xxx")) { - System.err.println("method name: " + methodNode.name); - Assertions.assertThat( - AsmUtils.findMethodInsnNode(methodNode, Type.getInternalName(SpyAPI.class), "atBeforeInvoke")) - .size().isEqualTo(1); - } - } - - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeCheckLocationFilterTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeCheckLocationFilterTest.java deleted file mode 100644 index 7fd58688d..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeCheckLocationFilterTest.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location.filter; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtInvoke; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtInvokeException; -import com.taobao.arthas.bytekit.asm.interceptor.parser.DefaultInterceptorClassParser; -import com.taobao.arthas.bytekit.asm.location.LocationType; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.Decompiler; -import com.taobao.arthas.bytekit.utils.MatchUtils; -import com.taobao.arthas.bytekit.utils.VerifyUtils; - -/** - * - * @author hengyunabc 2020-05-04 - * - */ -public class InvokeCheckLocationFilterTest { - - public static class SpyTraceInterceptor { - @AtInvoke(name = "", inline = true, whenComplete = false, excludes = { "java.**", "**SpyAPI**" }) - public static void onInvoke(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeMethodDeclaration String methodDesc, @Binding.InvokeMethodOwner String owner, - @Binding.InvokeMethodName String methodName) { - SpyAPI.atBeforeInvoke(clazz, owner, methodName, methodDesc, target); - } - - @AtInvoke(name = "", inline = true, whenComplete = true, excludes = { "java.**", "**SpyAPI**" }) - public static void onInvokeAfter(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeMethodDeclaration String methodDesc, @Binding.InvokeMethodOwner String owner, - @Binding.InvokeMethodName String methodName) { - SpyAPI.atAfterInvoke(clazz, owner, methodName, methodDesc, target); - } - - @AtInvokeException(name = "", inline = true, excludes = { "java.**", "**SpyAPI**" }) - public static void onInvokeException(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeMethodDeclaration String methodDesc, @Binding.InvokeMethodOwner String owner, - @Binding.InvokeMethodName String methodName, @Binding.Throwable Throwable throwable) { - SpyAPI.atInvokeException(clazz, owner, methodName, methodDesc, target, throwable); - } - } - - public static class SpyTraceInterceptor2 { - @AtInvoke(name = "", inline = true, whenComplete = false, excludes = { "**SpyAPI**" }) - public static void onInvoke(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeMethodDeclaration String methodDesc, @Binding.InvokeMethodOwner String owner, - @Binding.InvokeMethodName String methodName) { - SpyAPI.atBeforeInvoke(clazz, owner, methodName, methodDesc, target); - } - - @AtInvoke(name = "", inline = true, whenComplete = true, excludes = { "**SpyAPI**" }) - public static void onInvokeAfter(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeMethodDeclaration String methodDesc, @Binding.InvokeMethodOwner String owner, - @Binding.InvokeMethodName String methodName) { - SpyAPI.atAfterInvoke(clazz, owner, methodName, methodDesc, target); - } - - @AtInvokeException(name = "", inline = true, excludes = { "**SpyAPI**" }) - public static void onInvokeException(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.InvokeMethodDeclaration String methodDesc, @Binding.InvokeMethodOwner String owner, - @Binding.InvokeMethodName String methodName, @Binding.Throwable Throwable throwable) { - SpyAPI.atInvokeException(clazz, owner, methodName, methodDesc, target, throwable); - } - } - - public static class SpyAPI { - - public static void atBeforeInvoke(Class clazz, String owner, String methodName, String methodDesc, - Object target) { - - } - - public static void atInvokeException(Class clazz, String owner, String methodName, String methodDesc, - Object target, Throwable throwable) { - - } - - public static void atAfterInvoke(Class clazz, String owner, String methodName, String methodDesc, - Object target) { - - } - - } - - public static class TestAAA { - - int i = 0; - long l = 0; - - public TestAAA() { - xxx(1, 134L); - } - - public String hello(String str) { - - String result = ""; - - xxx(i, l); - - return result; - - } - - public String xxx(int i, long l) { - return "" + i + l; - } - - } - - @Test - public void test() throws Exception { - - DefaultInterceptorClassParser defaultInterceptorClassParser = new DefaultInterceptorClassParser(); - - List interceptorProcessors = defaultInterceptorClassParser - .parse(SpyTraceInterceptor.class); - - ClassNode classNode = AsmUtils.loadClass(TestAAA.class); - - List matchedMethods = new ArrayList(); - for (MethodNode methodNode : classNode.methods) { - if (MatchUtils.wildcardMatch(methodNode.name, "*")) { - matchedMethods.add(methodNode); - } - } - - LocationFilter enterFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), "atBeforeInvoke", - LocationType.INVOKE); - LocationFilter existFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), - "atInvokeException", LocationType.INVOKE_COMPLETED); - LocationFilter exceptionFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), - "atInvokeException", LocationType.INVOKE_EXCEPTION_EXIT); - GroupLocationFilter groupLocationFilter = new GroupLocationFilter(); - groupLocationFilter.addFilter(enterFilter); - groupLocationFilter.addFilter(existFilter); - groupLocationFilter.addFilter(exceptionFilter); - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - byte[] bytes = AsmUtils.toBytes(classNode); - VerifyUtils.asmVerify(bytes); - - VerifyUtils.instanceVerity(bytes); - - System.out.println(Decompiler.decompile(bytes)); - - ClassNode classNode2 = AsmUtils.toClassNode(bytes); - for (MethodNode methodNode : classNode2.methods) { - if (!methodNode.name.equals("xxx")) { - System.err.println("method name: " + methodNode.name); - Assertions.assertThat( - AsmUtils.findMethodInsnNode(methodNode, Type.getInternalName(SpyAPI.class), "atBeforeInvoke")) - .size().isEqualTo(1); - } - } - - } - - - @Test - public void test2() throws Exception { - - DefaultInterceptorClassParser defaultInterceptorClassParser = new DefaultInterceptorClassParser(); - - List interceptorProcessors = defaultInterceptorClassParser - .parse(SpyTraceInterceptor2.class); - - ClassNode classNode = AsmUtils.loadClass(TestAAA.class); - - List matchedMethods = new ArrayList(); - for (MethodNode methodNode : classNode.methods) { - if (MatchUtils.wildcardMatch(methodNode.name, "*")) { - matchedMethods.add(methodNode); - } - } - - LocationFilter enterFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), "atBeforeInvoke", - LocationType.INVOKE); - LocationFilter existFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), - "atInvokeException", LocationType.INVOKE_COMPLETED); - LocationFilter exceptionFilter = new InvokeCheckLocationFilter(Type.getInternalName(SpyAPI.class), - "atInvokeException", LocationType.INVOKE_EXCEPTION_EXIT); - GroupLocationFilter groupLocationFilter = new GroupLocationFilter(); - groupLocationFilter.addFilter(enterFilter); - groupLocationFilter.addFilter(existFilter); - groupLocationFilter.addFilter(exceptionFilter); - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - byte[] bytes = AsmUtils.toBytes(classNode); - VerifyUtils.asmVerify(bytes); - - VerifyUtils.instanceVerity(bytes); - - System.out.println(Decompiler.decompile(bytes)); - - ClassNode classNode2 = AsmUtils.toClassNode(bytes); - for (MethodNode methodNode : classNode2.methods) { - if (!methodNode.name.equals("xxx")) { - System.err.println("method name: " + methodNode.name); - Assertions.assertThat( - AsmUtils.findMethodInsnNode(methodNode, Type.getInternalName(SpyAPI.class), "atBeforeInvoke")) - .size().isEqualTo(1); - } - } - - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeContainLocationFilterTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeContainLocationFilterTest.java deleted file mode 100644 index 6b12eb9b0..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/asm/location/filter/InvokeContainLocationFilterTest.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.taobao.arthas.bytekit.asm.location.filter; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; -import com.taobao.arthas.bytekit.asm.MethodProcessor; -import com.taobao.arthas.bytekit.asm.binding.Binding; -import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtEnter; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExceptionExit; -import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExit; -import com.taobao.arthas.bytekit.asm.interceptor.parser.DefaultInterceptorClassParser; -import com.taobao.arthas.bytekit.asm.location.LocationType; -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.Decompiler; -import com.taobao.arthas.bytekit.utils.MatchUtils; -import com.taobao.arthas.bytekit.utils.VerifyUtils; - -/** - * - * @author hengyunabc 2020-05-04 - * - */ -public class InvokeContainLocationFilterTest { - - public static class SpyInterceptor { - - @AtEnter(inline = true) - public static void atEnter(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.MethodName String methodName, @Binding.MethodDesc String methodDesc, - @Binding.Args Object[] args) { - SpyAPI.atEnter(clazz, methodName, methodDesc, target, args); - } - - @AtExit(inline = true) - public static void atExit(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.MethodName String methodName, @Binding.MethodDesc String methodDesc, - @Binding.Args Object[] args, @Binding.Return Object returnObj) { - SpyAPI.atExit(clazz, methodName, methodDesc, target, args, returnObj); - } - - @AtExceptionExit(inline = true) - public static void atExceptionExit(@Binding.This Object target, @Binding.Class Class clazz, - @Binding.MethodName String methodName, @Binding.MethodDesc String methodDesc, - @Binding.Args Object[] args, @Binding.Throwable Throwable throwable) { - SpyAPI.atExceptionExit(clazz, methodName, methodDesc, target, args, throwable); - } - } - - public static class SpyAPI { - - public static void atEnter(Class clazz, String methodName, String methodDesc, Object target, Object[] args) { - - } - - public static void atExceptionExit(Class clazz, String methodName, String methodDesc, Object target, - Object[] args, Throwable throwable) { - - } - - public static void atExit(Class clazz, String methodName, String methodDesc, Object target, Object[] args, - Object returnObj) { - - } - - } - - public static class TestAAA { - - int i = 0; - long l = 0; - - public String hello(String str) { - - String result = ""; - - xxx(i, l); - - return result; - - } - - public String xxx(int i, long l) { - return "" + i + l; - } - - } - - @Test - public void test() throws Exception { - - DefaultInterceptorClassParser defaultInterceptorClassParser = new DefaultInterceptorClassParser(); - - List interceptorProcessors = defaultInterceptorClassParser.parse(SpyInterceptor.class); - - ClassNode classNode = AsmUtils.loadClass(TestAAA.class); - - List matchedMethods = new ArrayList(); - for (MethodNode methodNode : classNode.methods) { - if (MatchUtils.wildcardMatch(methodNode.name, "*")) { - matchedMethods.add(methodNode); - } - } - - LocationFilter enterFilter = new InvokeContainLocationFilter(Type.getInternalName(SpyAPI.class), "atEnter", - LocationType.ENTER); - LocationFilter existFilter = new InvokeContainLocationFilter(Type.getInternalName(SpyAPI.class), "atExit", - LocationType.EXIT); - LocationFilter exceptionFilter = new InvokeContainLocationFilter(Type.getInternalName(SpyAPI.class), - "atExceptionExit", LocationType.EXCEPTION_EXIT); - GroupLocationFilter groupLocationFilter = new GroupLocationFilter(); - groupLocationFilter.addFilter(enterFilter); - groupLocationFilter.addFilter(existFilter); - groupLocationFilter.addFilter(exceptionFilter); - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - for (MethodNode methodNode : matchedMethods) { - MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode, groupLocationFilter); - for (InterceptorProcessor interceptor : interceptorProcessors) { - interceptor.process(methodProcessor); - } - } - - byte[] bytes = AsmUtils.toBytes(classNode); - VerifyUtils.asmVerify(bytes); - - System.out.println(Decompiler.decompile(bytes)); - - ClassNode classNode2 = AsmUtils.toClassNode(bytes); - for (MethodNode methodNode : classNode2.methods) { - System.err.println("method name: " + methodNode.name); - Assertions - .assertThat(AsmUtils.findMethodInsnNode(methodNode, Type.getInternalName(SpyAPI.class), "atEnter")) - .size().isEqualTo(1); - Assertions - .assertThat(AsmUtils.findMethodInsnNode(methodNode, Type.getInternalName(SpyAPI.class), "atExit")) - .size().isEqualTo(1); - Assertions - .assertThat(AsmUtils.findMethodInsnNode(methodNode, Type.getInternalName(SpyAPI.class), "atExceptionExit")) - .size().isEqualTo(1); - } - - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/AsmAnnotationUtilsTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/AsmAnnotationUtilsTest.java deleted file mode 100644 index 366fac9a7..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/AsmAnnotationUtilsTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.io.IOException; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.Arrays; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.springframework.stereotype.Service; - -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.taobao.arthas.bytekit.utils.AsmAnnotationUtils; -import com.taobao.arthas.bytekit.utils.AsmUtils; - -/** - * - * @author hengyunabc 2020-05-04 - * - */ -public class AsmAnnotationUtilsTest { - - @Target(value = { ElementType.TYPE, ElementType.METHOD }) - @Retention(value = RetentionPolicy.RUNTIME) - public @interface AdviceInfo { - - public String[] adviceInfos(); - } - - @Service - @AdviceInfo(adviceInfos = { "xxxx", "yyy" }) - static class AAA { - - @AdviceInfo(adviceInfos = { "mmm", "yyy" }) - public void test() { - - } - - } - - @Service - static class BBB { - public void test() { - } - } - - @Test - public void test() throws IOException { - ClassNode classNodeA = AsmUtils.loadClass(AAA.class); - - ClassNode classNodeB = AsmUtils.loadClass(BBB.class); - - Assertions.assertThat(AsmAnnotationUtils.queryAnnotationInfo(classNodeA.visibleAnnotations, - Type.getDescriptor(AdviceInfo.class), "adviceInfos")).isEqualTo(Arrays.asList("xxxx", "yyy")); - - AsmAnnotationUtils.addAnnotationInfo(classNodeA.visibleAnnotations, Type.getDescriptor(AdviceInfo.class), - "adviceInfos", "fff"); - - Assertions - .assertThat(AsmAnnotationUtils.queryAnnotationInfo(classNodeA.visibleAnnotations, - Type.getDescriptor(AdviceInfo.class), "adviceInfos")) - .isEqualTo(Arrays.asList("xxxx", "yyy", "fff")); - - Assertions.assertThat(AsmAnnotationUtils.queryAnnotationInfo(classNodeB.visibleAnnotations, - Type.getDescriptor(AdviceInfo.class), "adviceInfos")).isEmpty(); - - AsmAnnotationUtils.addAnnotationInfo(classNodeB.visibleAnnotations, Type.getDescriptor(AdviceInfo.class), - "adviceInfos", "fff"); - - Assertions.assertThat(AsmAnnotationUtils.queryAnnotationInfo(classNodeB.visibleAnnotations, - Type.getDescriptor(AdviceInfo.class), "adviceInfos")).isEqualTo(Arrays.asList("fff")); - - } - -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/AsmUtilsTest.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/AsmUtilsTest.java deleted file mode 100644 index 21c122b16..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/AsmUtilsTest.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -import java.io.IOException; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import com.alibaba.arthas.deps.org.objectweb.asm.ClassWriter; -import com.alibaba.arthas.deps.org.objectweb.asm.MethodVisitor; -import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes; -import com.alibaba.arthas.deps.org.objectweb.asm.Type; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode; -import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode; - -import com.taobao.arthas.bytekit.utils.AsmUtils; -import com.taobao.arthas.bytekit.utils.VerifyUtils; - -public class AsmUtilsTest { - - abstract static class TestClass { - public static synchronized List sss(int i, long l, List list) throws IOException, ArrayIndexOutOfBoundsException { - return null; - } - protected abstract String hello(String ss); - } - - static class TestConstructorClass { - public TestConstructorClass(int i, String s) { - - } - } - - @Test - public void testMethodDeclaration() throws IOException { - ClassNode classNode = AsmUtils.loadClass(TestClass.class); - MethodNode sss = AsmUtils.findFirstMethod(classNode.methods, "sss"); - - MethodNode hello = AsmUtils.findFirstMethod(classNode.methods, "hello"); - - MethodNode constructor = AsmUtils.findFirstMethod(AsmUtils.loadClass(TestConstructorClass.class).methods, ""); - - String helloDeclaration = AsmUtils.methodDeclaration(Type.getType(TestClass.class), hello); - String sssDeclaration = AsmUtils.methodDeclaration(Type.getType(TestClass.class), sss); - - String constructorDeclaration = AsmUtils.methodDeclaration(Type.getType(TestConstructorClass.class), constructor); - - System.err.println(helloDeclaration); - System.err.println(sssDeclaration); - System.err.println(constructorDeclaration); - - Assertions.assertThat(helloDeclaration).isEqualTo("protected abstract java.lang.String hello(java.lang.String)"); - Assertions.assertThat(sssDeclaration).isEqualTo( - "public static synchronized java.util.List sss(int, long, java.util.List) throws java.io.IOException, java.lang.ArrayIndexOutOfBoundsException"); - Assertions.assertThat(constructorDeclaration).isEqualTo("public com.taobao.arthas.bytekit.utils.AsmUtilsTest$TestConstructorClass(int, java.lang.String)"); - } - - public static byte[] emptyMethodBytes() throws Exception { - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - - cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, "LEmptyClass", null, "java/lang/Object", null); - - { - mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(Opcodes.ALOAD, 0); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { - mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "emptyMethod", "()V", null, null); - // mv.visitCode(); - mv.visitInsn(Opcodes.RETURN); - // mv.visitMaxs(0, 0); - // mv.visitEnd(); - } - cw.visitEnd(); - - return cw.toByteArray(); - } - - @Test - public void emptyMethodTest() throws Exception { - - byte[] emptyMethodBytes = emptyMethodBytes(); - - VerifyUtils.asmVerify(emptyMethodBytes); - VerifyUtils.instanceVerity(emptyMethodBytes); - - ClassNode classNode = AsmUtils.toClassNode(emptyMethodBytes); - MethodNode methodNode = AsmUtils.findFirstMethod(classNode.methods, "emptyMethod"); - - AbstractInsnNode first = methodNode.instructions.getFirst(); - AbstractInsnNode last = methodNode.instructions.getLast(); - System.err.println(first); - System.err.println(last); - - int size = methodNode.instructions.size(); - for (int i = 0; i < size; ++i) { - System.err.println(methodNode.instructions.get(i)); - } - - // String asmCode = AsmUtils.toASMCode(classNode); - // System.err.println(asmCode); - } - - private String aaa = ""; - public void xxx () { - aaa = "bbb"; - } - - @Test - public void testFieldAccess() throws IOException { - ClassNode classNode = AsmUtils.loadClass(AsmUtilsTest.class); - - MethodNode methodNode = AsmUtils.findFirstMethod(classNode.methods, "xxx"); - - int size = methodNode.instructions.size(); - for (int i = 0; i < size; ++i) { - System.err.println(methodNode.instructions.get(i)); - } - - - } - - - @Test - public void testRenameClass() throws Exception { - ClassNode classNode = AsmUtils.loadClass(AsmUtilsTest.class); - - byte[] classBytes = AsmUtils.toBytes(classNode); - - byte[] renameClass = AsmUtils.renameClass(classBytes, "com.test.Test.XXX"); - - VerifyUtils.asmVerify(renameClass); - Object object = VerifyUtils.instanceVerity(renameClass); - - Assertions.assertThat(object.getClass().getName()).isEqualTo("com.test.Test.XXX"); - } - - @Test - public void testGetMajorVersion() throws Exception { - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V1_1)).isEqualTo(45); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V1_2)).isEqualTo(46); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V1_3)).isEqualTo(47); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V1_4)).isEqualTo(48); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V1_5)).isEqualTo(49); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V1_6)).isEqualTo(50); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V1_7)).isEqualTo(51); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V1_8)).isEqualTo(52); - - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V9)).isEqualTo(53); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V10)).isEqualTo(54); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V11)).isEqualTo(55); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V12)).isEqualTo(56); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V13)).isEqualTo(57); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V14)).isEqualTo(58); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V15)).isEqualTo(59); - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V16)).isEqualTo(60); - - Assertions.assertThat(AsmUtils.getMajorVersion(Opcodes.V16 | Opcodes.V_PREVIEW)).isEqualTo(60); - } - - @Test - public void testSetMajorVersion() throws Exception { - int version = Opcodes.V16 | Opcodes.V_PREVIEW; - int newVersion = AsmUtils.setMajorVersion(version, 58); - - AsmUtils.getMajorVersion(newVersion); - - Assertions.assertThat(AsmUtils.getMajorVersion(newVersion)).isEqualTo(58); - } -} diff --git a/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/EmptyClass.java b/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/EmptyClass.java deleted file mode 100644 index 4e5399ae4..000000000 --- a/bytekit/src/test/java/com/taobao/arthas/bytekit/utils/EmptyClass.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.taobao.arthas.bytekit.utils; - -public class EmptyClass { - - public static void emptyMethod() { - - } - -} diff --git a/core/pom.xml b/core/pom.xml index 88979b918..684e3d822 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -121,10 +121,10 @@ ${project.version} - com.taobao.arthas - arthas-bytekit - ${project.version} + com.alibaba + bytekit-core + net.bytebuddy byte-buddy-agent diff --git a/pom.xml b/pom.xml index 2ac640246..25173136c 100644 --- a/pom.xml +++ b/pom.xml @@ -59,7 +59,6 @@ spy common tunnel-client - bytekit core agent client @@ -134,6 +133,11 @@ + + com.alibaba + bytekit-core + 0.0.1 + org.benf cfr