From a55b471ea7ddc261ea6ca441b1dc5b52e59e5db3 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Wed, 20 May 2020 01:47:11 +0800 Subject: [PATCH] clean code --- .../arthas/core/advisor/AdviceWeaver.java | 705 +----------------- 1 file changed, 4 insertions(+), 701 deletions(-) diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/AdviceWeaver.java b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceWeaver.java index aa84db690..2b607da6f 100644 --- a/core/src/main/java/com/taobao/arthas/core/advisor/AdviceWeaver.java +++ b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceWeaver.java @@ -1,24 +1,11 @@ package com.taobao.arthas.core.advisor; -import com.alibaba.arthas.deps.org.slf4j.Logger; -import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; -import com.taobao.arthas.core.GlobalOptions; -import com.taobao.arthas.core.util.matcher.Matcher; -import com.taobao.arthas.core.util.*; -import com.taobao.arthas.core.util.affect.EnhancerAffect; -import com.taobao.arthas.core.util.collection.GaStack; -import com.taobao.arthas.core.util.collection.ThreadUnsafeFixGaStack; -import com.taobao.arthas.core.util.collection.ThreadUnsafeGaStack; -import org.objectweb.asm.*; -import org.objectweb.asm.commons.AdviceAdapter; -import org.objectweb.asm.commons.JSRInlinerAdapter; -import org.objectweb.asm.commons.Method; - -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import com.alibaba.arthas.deps.org.slf4j.Logger; +import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; + /** * 通知编织者
*

@@ -27,36 +14,13 @@ import java.util.concurrent.ConcurrentHashMap; *

* Created by vlinux on 15/5/17. */ -public class AdviceWeaver extends ClassVisitor implements Opcodes { +public class AdviceWeaver { private static final Logger logger = LoggerFactory.getLogger(AdviceWeaver.class); - public static final String ON_BEFORE = "methodOnBegin"; - public static final String ON_RETURN = "methodOnReturnEnd"; - public static final String ON_THROWS = "methodOnThrowingEnd"; - public static final String BEFORE_INVOKE = "methodOnInvokeBeforeTracing"; - public static final String AFTER_INVOKE = "methodOnInvokeAfterTracing"; - public static final String THROW_INVOKE = "methodOnInvokeThrowTracing"; - public static final String RESET = "resetArthasClassLoader"; - - // 线程帧栈堆栈大小 - private final static int FRAME_STACK_SIZE = 7; // 通知监听器集合 private final static Map advices = new ConcurrentHashMap(); - // 线程帧封装 - private static final ThreadLocal>> threadBoundContext - = new ThreadLocal>>(); - // 防止自己递归调用 - private static final ThreadLocal isSelfCallRef = new ThreadLocal() { - - @Override - protected Boolean initialValue() { - return false; - } - - }; - /** * 注册监听器 @@ -112,665 +76,4 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { return advices.remove(adviceId); } - private final int adviceId; - private final boolean isTracing; - private final boolean skipJDKTrace; - private final String className; - private String superName; - private final Matcher matcher; - private final EnhancerAffect affect; - - - /** - * 构建通知编织器 - * - * @param adviceId 通知ID - * @param isTracing 可跟踪方法调用 - * @param skipJDKTrace 是否忽略对JDK内部方法的跟踪 - * @param className 类名称 - * @param matcher 方法匹配 - * 只有匹配上的方法才会被织入通知器 - * @param affect 影响计数 - * @param cv ClassVisitor for ASM - */ - public AdviceWeaver(int adviceId, boolean isTracing, boolean skipJDKTrace, String className, Matcher matcher, EnhancerAffect affect, ClassVisitor cv) { - super(Opcodes.ASM8, cv); - this.adviceId = adviceId; - this.isTracing = isTracing; - this.skipJDKTrace = skipJDKTrace; - this.className = className; - this.matcher = matcher; - this.affect = affect; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, name, signature, superName, interfaces); - this.superName = superName; - } - - protected boolean isSuperOrSiblingConstructorCall(int opcode, String owner, String name) { - return (opcode == Opcodes.INVOKESPECIAL && name.equals("") - && (superName.equals(owner) || className.equals(owner))); - } - - /** - * 是否抽象属性 - */ - private boolean isAbstract(int access) { - return (ACC_ABSTRACT & access) == ACC_ABSTRACT; - } - - - /** - * 是否需要忽略 - */ - private boolean isIgnore(MethodVisitor mv, int access, String methodName) { - return null == mv - || isAbstract(access) - || !matcher.matching(methodName) - || ArthasCheckUtils.isEquals(methodName, ""); - } - - @Override - public MethodVisitor visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) { - - final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); - - if (isIgnore(mv, access, name)) { - return mv; - } - - // 编织方法计数 - affect.mCnt(1); - - return new AdviceAdapter(Opcodes.ASM8, new JSRInlinerAdapter(mv, access, name, desc, signature, exceptions), access, name, desc) { - - // -- Label for try...catch block - private final Label beginLabel = new Label(); - private final Label endLabel = new Label(); - - // -- KEY of advice -- - private final int KEY_ARTHAS_ADVICE_BEFORE_METHOD = 0; - private final int KEY_ARTHAS_ADVICE_RETURN_METHOD = 1; - private final int KEY_ARTHAS_ADVICE_THROWS_METHOD = 2; - private final int KEY_ARTHAS_ADVICE_BEFORE_INVOKING_METHOD = 3; - private final int KEY_ARTHAS_ADVICE_AFTER_INVOKING_METHOD = 4; - private final int KEY_ARTHAS_ADVICE_THROW_INVOKING_METHOD = 5; - - - // -- KEY of ASM_TYPE or ASM_METHOD -- - private final Type ASM_TYPE_SPY = Type.getType("Ljava/arthas/Spy;"); - private final Type ASM_TYPE_OBJECT = Type.getType(Object.class); - private final Type ASM_TYPE_OBJECT_ARRAY = Type.getType(Object[].class); - private final Type ASM_TYPE_CLASS = Type.getType(Class.class); - private final Type ASM_TYPE_INTEGER = Type.getType(Integer.class); - private final Type ASM_TYPE_CLASS_LOADER = Type.getType(ClassLoader.class); - private final Type ASM_TYPE_STRING = Type.getType(String.class); - private final Type ASM_TYPE_THROWABLE = Type.getType(Throwable.class); - private final Type ASM_TYPE_INT = Type.getType(int.class); - private final Type ASM_TYPE_METHOD = Type.getType(java.lang.reflect.Method.class); - private final Method ASM_METHOD_METHOD_INVOKE = Method.getMethod("Object invoke(Object,Object[])"); - - // 代码锁 - private final CodeLock codeLockForTracing = new TracingAsmCodeLock(this); - - private int lineNumber; - - private void _debug(final StringBuilder append, final String msg) { - - if (!GlobalOptions.isDebugForAsm) { - return; - } - - // println msg - visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); - if (StringUtils.isBlank(append.toString())) { - visitLdcInsn(append.append(msg).toString()); - } else { - visitLdcInsn(append.append(" >> ").append(msg).toString()); - } - - visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); - } - -// private void _debug_dup(final String msg) { -// -// if (!isDebugForAsm) { -// return; -// } -// -// // print prefix -// visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); -// visitLdcInsn(msg); -// visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); -// -// // println msg -// dup(); -// visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); -// swap(); -// visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false); -// visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); -// } - - /** - * 加载通知方法 - * @param keyOfMethod 通知方法KEY - */ - private void loadAdviceMethod(int keyOfMethod) { - - switch (keyOfMethod) { - - case KEY_ARTHAS_ADVICE_BEFORE_METHOD: { - getStatic(ASM_TYPE_SPY, "ON_BEFORE_METHOD", ASM_TYPE_METHOD); - break; - } - - case KEY_ARTHAS_ADVICE_RETURN_METHOD: { - getStatic(ASM_TYPE_SPY, "ON_RETURN_METHOD", ASM_TYPE_METHOD); - break; - } - - case KEY_ARTHAS_ADVICE_THROWS_METHOD: { - getStatic(ASM_TYPE_SPY, "ON_THROWS_METHOD", ASM_TYPE_METHOD); - break; - } - - case KEY_ARTHAS_ADVICE_BEFORE_INVOKING_METHOD: { - getStatic(ASM_TYPE_SPY, "BEFORE_INVOKING_METHOD", ASM_TYPE_METHOD); - break; - } - - case KEY_ARTHAS_ADVICE_AFTER_INVOKING_METHOD: { - getStatic(ASM_TYPE_SPY, "AFTER_INVOKING_METHOD", ASM_TYPE_METHOD); - break; - } - - case KEY_ARTHAS_ADVICE_THROW_INVOKING_METHOD: { - getStatic(ASM_TYPE_SPY, "THROW_INVOKING_METHOD", ASM_TYPE_METHOD); - break; - } - - default: { - throw new IllegalArgumentException("illegal keyOfMethod=" + keyOfMethod); - } - - } - - } - - /** - * 加载ClassLoader
- * 这里分开静态方法中ClassLoader的获取以及普通方法中ClassLoader的获取 - * 主要是性能上的考虑 - */ - private void loadClassLoader() { - - if (this.isStaticMethod()) { - visitLdcInsn(StringUtils.normalizeClassName(className)); - invokeStatic(ASM_TYPE_CLASS, Method.getMethod("Class forName(String)")); - invokeVirtual(ASM_TYPE_CLASS, Method.getMethod("ClassLoader getClassLoader()")); - - } else { - loadThis(); - invokeVirtual(ASM_TYPE_OBJECT, Method.getMethod("Class getClass()")); - invokeVirtual(ASM_TYPE_CLASS, Method.getMethod("ClassLoader getClassLoader()")); - } - - } - - /** - * 加载before通知参数数组 - */ - private void loadArrayForBefore() { - push(7); - newArray(ASM_TYPE_OBJECT); - - dup(); - push(0); - push(adviceId); - box(ASM_TYPE_INT); - arrayStore(ASM_TYPE_INTEGER); - - dup(); - push(1); - loadClassLoader(); - arrayStore(ASM_TYPE_CLASS_LOADER); - - dup(); - push(2); - push(className); - arrayStore(ASM_TYPE_STRING); - - dup(); - push(3); - push(name); - arrayStore(ASM_TYPE_STRING); - - dup(); - push(4); - push(desc); - arrayStore(ASM_TYPE_STRING); - - dup(); - push(5); - loadThisOrPushNullIfIsStatic(); - arrayStore(ASM_TYPE_OBJECT); - - dup(); - push(6); - loadArgArray(); - arrayStore(ASM_TYPE_OBJECT_ARRAY); - } - - - @Override - protected void onMethodEnter() { - - codeLockForTracing.lock(new CodeLock.Block() { - @Override - public void code() { - - final StringBuilder append = new StringBuilder(); - _debug(append, "debug:onMethodEnter()"); - - // 加载before方法 - loadAdviceMethod(KEY_ARTHAS_ADVICE_BEFORE_METHOD); - - _debug(append, "debug:onMethodEnter() > loadAdviceMethod()"); - - // 推入Method.invoke()的第一个参数 - pushNull(); - - // 方法参数 - loadArrayForBefore(); - - _debug(append, "debug:onMethodEnter() > loadAdviceMethod() > loadArrayForBefore()"); - - // 调用方法 - invokeVirtual(ASM_TYPE_METHOD, ASM_METHOD_METHOD_INVOKE); - pop(); - - _debug(append, "debug:onMethodEnter() > loadAdviceMethod() > loadArrayForBefore() > invokeVirtual()"); - } - }); - - mark(beginLabel); - - } - - - /* - * 加载return通知参数数组 - */ - private void loadReturnArgs() { - dup2X1(); - pop2(); - push(1); - newArray(ASM_TYPE_OBJECT); - dup(); - dup2X1(); - pop2(); - push(0); - swap(); - arrayStore(ASM_TYPE_OBJECT); - } - - @Override - protected void onMethodExit(final int opcode) { - - if (!isThrow(opcode)) { - codeLockForTracing.lock(new CodeLock.Block() { - @Override - public void code() { - - final StringBuilder append = new StringBuilder(); - _debug(append, "debug:onMethodExit()"); - - // 加载返回对象 - loadReturn(opcode); - _debug(append, "debug:onMethodExit() > loadReturn()"); - - - // 加载returning方法 - loadAdviceMethod(KEY_ARTHAS_ADVICE_RETURN_METHOD); - _debug(append, "debug:onMethodExit() > loadReturn() > loadAdviceMethod()"); - - // 推入Method.invoke()的第一个参数 - pushNull(); - - // 加载return通知参数数组 - loadReturnArgs(); - _debug(append, "debug:onMethodExit() > loadReturn() > loadAdviceMethod() > loadReturnArgs()"); - - invokeVirtual(ASM_TYPE_METHOD, ASM_METHOD_METHOD_INVOKE); - pop(); - - _debug(append, "debug:onMethodExit() > loadReturn() > loadAdviceMethod() > loadReturnArgs() > invokeVirtual()"); - } - }); - } - - } - - - /* - * 创建throwing通知参数本地变量 - */ - private void loadThrowArgs() { - dup2X1(); - pop2(); - push(1); - newArray(ASM_TYPE_OBJECT); - dup(); - dup2X1(); - pop2(); - push(0); - swap(); - arrayStore(ASM_TYPE_THROWABLE); - } - - @Override - public void visitMaxs(int maxStack, int maxLocals) { - - mark(endLabel); -// catchException(beginLabel, endLabel, ASM_TYPE_THROWABLE); - visitTryCatchBlock(beginLabel, endLabel, mark(), - ASM_TYPE_THROWABLE.getInternalName()); - - codeLockForTracing.lock(new CodeLock.Block() { - @Override - public void code() { - - final StringBuilder append = new StringBuilder(); - _debug(append, "debug:catchException()"); - - // 加载异常 - loadThrow(); - _debug(append, "debug:catchException() > loadThrow() > loadAdviceMethod()"); - - // 加载throwing方法 - loadAdviceMethod(KEY_ARTHAS_ADVICE_THROWS_METHOD); - _debug(append, "debug:catchException() > loadThrow() > loadAdviceMethod()"); - - - // 推入Method.invoke()的第一个参数 - pushNull(); - - // 加载throw通知参数数组 - loadThrowArgs(); - _debug(append, "debug:catchException() > loadThrow() > loadAdviceMethod() > loadThrowArgs()"); - - // 调用方法 - invokeVirtual(ASM_TYPE_METHOD, ASM_METHOD_METHOD_INVOKE); - pop(); - _debug(append, "debug:catchException() > loadThrow() > loadAdviceMethod() > loadThrowArgs() > invokeVirtual()"); - - } - }); - - throwException(); - - super.visitMaxs(maxStack, maxLocals); - } - - @Override - public void visitLineNumber(int line, Label start) { - super.visitLineNumber(line, start); - lineNumber = line; - } - - /** - * 是否静态方法 - * @return true:静态方法 / false:非静态方法 - */ - private boolean isStaticMethod() { - return (methodAccess & ACC_STATIC) != 0; - } - - /** - * 是否抛出异常返回(通过字节码判断) - * @param opcode 操作码 - * @return true:以抛异常形式返回 / false:非抛异常形式返回(return) - */ - private boolean isThrow(int opcode) { - return opcode == ATHROW; - } - - /** - * 将NULL推入堆栈 - */ - private void pushNull() { - push((Type) null); - } - - /** - * 加载this/null - */ - private void loadThisOrPushNullIfIsStatic() { - if (isStaticMethod()) { - pushNull(); - } else { - loadThis(); - } - } - - /** - * 加载返回值 - * @param opcode 操作吗 - */ - private void loadReturn(int opcode) { - switch (opcode) { - - case RETURN: { - pushNull(); - break; - } - - case ARETURN: { - dup(); - break; - } - - case LRETURN: - case DRETURN: { - dup2(); - box(Type.getReturnType(methodDesc)); - break; - } - - default: { - dup(); - box(Type.getReturnType(methodDesc)); - break; - } - - } - } - - /** - * 加载异常 - */ - private void loadThrow() { - dup(); - } - - - /** - * 加载方法调用跟踪通知所需参数数组 - */ - private void loadArrayForInvokeTracing(String owner, String name, String desc, int lineNumber) { - push(5); - newArray(ASM_TYPE_OBJECT); - - dup(); - push(0); - push(adviceId); - box(ASM_TYPE_INT); - arrayStore(ASM_TYPE_INTEGER); - - dup(); - push(1); - push(owner); - arrayStore(ASM_TYPE_STRING); - - dup(); - push(2); - push(name); - arrayStore(ASM_TYPE_STRING); - - dup(); - push(3); - push(desc); - arrayStore(ASM_TYPE_STRING); - - dup(); - push(4); - push(lineNumber); - box(ASM_TYPE_INT); - arrayStore(ASM_TYPE_INTEGER); - } - - - @Override - public void visitInsn(int opcode) { - super.visitInsn(opcode); - codeLockForTracing.code(opcode); - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - tcbs.add(new AsmTryCatchBlock(start, end, handler, type)); - } - - List tcbs = new ArrayList(); - - @Override - public void visitEnd() { - for (AsmTryCatchBlock tcb : tcbs) { - super.visitTryCatchBlock(tcb.start, tcb.end, tcb.handler, tcb.type); - } - - super.visitEnd(); - } - - /* - * 跟踪代码 - */ - private void tracing(final int tracingType, final String owner, final String name, final String desc, final int lineNumber) { - - final String label; - switch (tracingType) { - case KEY_ARTHAS_ADVICE_BEFORE_INVOKING_METHOD: { - label = "beforeInvoking"; - break; - } - case KEY_ARTHAS_ADVICE_AFTER_INVOKING_METHOD: { - label = "afterInvoking"; - break; - } - case KEY_ARTHAS_ADVICE_THROW_INVOKING_METHOD: { - label = "throwInvoking"; - break; - } - default: { - throw new IllegalStateException("illegal tracing type: " + tracingType); - } - } - - codeLockForTracing.lock(new CodeLock.Block() { - @Override - public void code() { - - final StringBuilder append = new StringBuilder(); - _debug(append, "debug:" + label + "()"); - - loadAdviceMethod(tracingType); - _debug(append, "loadAdviceMethod()"); - - pushNull(); - loadArrayForInvokeTracing(owner, name, desc, lineNumber); - _debug(append, "loadArrayForInvokeTracing()"); - - invokeVirtual(ASM_TYPE_METHOD, ASM_METHOD_METHOD_INVOKE); - pop(); - _debug(append, "invokeVirtual()"); - - } - }); - - } - - @Override - public void visitMethodInsn(int opcode, final String owner, final String name, final String desc, boolean itf) { - if (isSuperOrSiblingConstructorCall(opcode, owner, name)) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - - if (!isTracing || codeLockForTracing.isLock()) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - - //是否要对JDK内部的方法调用进行trace - if (skipJDKTrace && owner.startsWith("java/")) { - super.visitMethodInsn(opcode, owner, name, desc, itf); - return; - } - - // 方法调用前通知 - tracing(KEY_ARTHAS_ADVICE_BEFORE_INVOKING_METHOD, owner, name, desc, lineNumber); - - final Label beginLabel = new Label(); - final Label endLabel = new Label(); - final Label finallyLabel = new Label(); - - // try - // { - - mark(beginLabel); - super.visitMethodInsn(opcode, owner, name, desc, itf); - mark(endLabel); - - // 方法调用后通知 - tracing(KEY_ARTHAS_ADVICE_AFTER_INVOKING_METHOD, owner, name, desc, lineNumber); - goTo(finallyLabel); - - // } - // catch - // { - - catchException(beginLabel, endLabel, ASM_TYPE_THROWABLE); - tracing(KEY_ARTHAS_ADVICE_THROW_INVOKING_METHOD, owner, name, desc, lineNumber); - - throwException(); - - // } - // finally - // { - mark(finallyLabel); - // } - } - }; - } - - static class AsmTryCatchBlock { - Label start; - Label end; - Label handler; - String type; - - AsmTryCatchBlock(Label start, Label end, Label handler, String type) { - this.start = start; - this.end = end; - this.handler = handler; - this.type = type; - } - } }