From e18837009987df410b1608c6025bd0070a180126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=BF=97=E6=AF=85?= Date: Thu, 9 May 2019 10:42:43 +0800 Subject: [PATCH] trace line number support (#668) --- .../taobao/arthas/agent/AgentBootstrap.java | 6 +-- boot/pom.xml | 1 - .../arthas/core/advisor/AdviceWeaver.java | 39 ++++++++++++------- .../arthas/core/advisor/InvokeTraceable.java | 12 ++++-- .../AbstractTraceAdviceListener.java | 3 +- .../monitor200/TraceAdviceListener.java | 8 ++-- 6 files changed, 44 insertions(+), 25 deletions(-) diff --git a/agent/src/main/java/com/taobao/arthas/agent/AgentBootstrap.java b/agent/src/main/java/com/taobao/arthas/agent/AgentBootstrap.java index adbba79d5..787307bd0 100644 --- a/agent/src/main/java/com/taobao/arthas/agent/AgentBootstrap.java +++ b/agent/src/main/java/com/taobao/arthas/agent/AgentBootstrap.java @@ -86,9 +86,9 @@ public class AgentBootstrap { String.class, String.class, Object.class, Object[].class); Method onReturn = adviceWeaverClass.getMethod(ON_RETURN, Object.class); Method onThrows = adviceWeaverClass.getMethod(ON_THROWS, Throwable.class); - Method beforeInvoke = adviceWeaverClass.getMethod(BEFORE_INVOKE, int.class, String.class, String.class, String.class); - Method afterInvoke = adviceWeaverClass.getMethod(AFTER_INVOKE, int.class, String.class, String.class, String.class); - Method throwInvoke = adviceWeaverClass.getMethod(THROW_INVOKE, int.class, String.class, String.class, String.class); + Method beforeInvoke = adviceWeaverClass.getMethod(BEFORE_INVOKE, int.class, String.class, String.class, String.class, int.class); + Method afterInvoke = adviceWeaverClass.getMethod(AFTER_INVOKE, int.class, String.class, String.class, String.class, int.class); + Method throwInvoke = adviceWeaverClass.getMethod(THROW_INVOKE, int.class, String.class, String.class, String.class, int.class); Method reset = AgentBootstrap.class.getMethod(RESET); Spy.initForAgentLauncher(classLoader, onBefore, onReturn, onThrows, beforeInvoke, afterInvoke, throwInvoke, reset); } diff --git a/boot/pom.xml b/boot/pom.xml index aaaceb078..e1b60cdc1 100644 --- a/boot/pom.xml +++ b/boot/pom.xml @@ -20,7 +20,6 @@ com.alibaba.middleware cli - junit junit 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 f2c709217..fc29f233a 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 @@ -171,11 +171,11 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { * @param name 调用方法名 * @param desc 调用方法描述 */ - public static void methodOnInvokeBeforeTracing(int adviceId, String owner, String name, String desc) { + public static void methodOnInvokeBeforeTracing(int adviceId, String owner, String name, String desc, int lineNumber) { final InvokeTraceable listener = (InvokeTraceable) getListener(adviceId); if (null != listener) { try { - listener.invokeBeforeTracing(owner, name, desc); + listener.invokeBeforeTracing(owner, name, desc, lineNumber); } catch (Throwable t) { logger.warn("advice before tracing failed.", t); } @@ -190,11 +190,11 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { * @param name 调用方法名 * @param desc 调用方法描述 */ - public static void methodOnInvokeAfterTracing(int adviceId, String owner, String name, String desc) { + public static void methodOnInvokeAfterTracing(int adviceId, String owner, String name, String desc, int lineNumber) { final InvokeTraceable listener = (InvokeTraceable) getListener(adviceId); if (null != listener) { try { - listener.invokeAfterTracing(owner, name, desc); + listener.invokeAfterTracing(owner, name, desc, lineNumber); } catch (Throwable t) { logger.warn("advice after tracing failed.", t); } @@ -209,11 +209,11 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { * @param name 调用方法名 * @param desc 调用方法描述 */ - public static void methodOnInvokeThrowTracing(int adviceId, String owner, String name, String desc) { + public static void methodOnInvokeThrowTracing(int adviceId, String owner, String name, String desc, int lineNumber) { final InvokeTraceable listener = (InvokeTraceable) getListener(adviceId); if (null != listener) { try { - listener.invokeThrowTracing(owner, name, desc); + listener.invokeThrowTracing(owner, name, desc, lineNumber); } catch (Throwable t) { logger.warn("advice throw tracing failed.", t); } @@ -442,6 +442,7 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { // 代码锁 private final CodeLock codeLockForTracing = new TracingAsmCodeLock(this); + private int lineNumber; private void _debug(final StringBuilder append, final String msg) { @@ -740,6 +741,12 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { super.visitMaxs(maxStack, maxLocals); } + @Override + public void visitLineNumber(int line, Label start) { + super.visitLineNumber(line, start); + lineNumber = line; + } + /** * 是否静态方法 * @return true:静态方法 / false:非静态方法 @@ -819,8 +826,8 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { /** * 加载方法调用跟踪通知所需参数数组 */ - private void loadArrayForInvokeTracing(String owner, String name, String desc) { - push(4); + private void loadArrayForInvokeTracing(String owner, String name, String desc, int lineNumber) { + push(5); newArray(ASM_TYPE_OBJECT); dup(); @@ -843,6 +850,12 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { push(3); push(desc); arrayStore(ASM_TYPE_STRING); + + dup(); + push(4); + push(lineNumber); + box(ASM_TYPE_INT); + arrayStore(ASM_TYPE_INTEGER); } @@ -871,7 +884,7 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { /* * 跟踪代码 */ - private void tracing(final int tracingType, final String owner, final String name, final String desc) { + private void tracing(final int tracingType, final String owner, final String name, final String desc, final int lineNumber) { final String label; switch (tracingType) { @@ -903,7 +916,7 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { _debug(append, "loadAdviceMethod()"); pushNull(); - loadArrayForInvokeTracing(owner, name, desc); + loadArrayForInvokeTracing(owner, name, desc, lineNumber); _debug(append, "loadArrayForInvokeTracing()"); invokeVirtual(ASM_TYPE_METHOD, ASM_METHOD_METHOD_INVOKE); @@ -934,7 +947,7 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { } // 方法调用前通知 - tracing(KEY_ARTHAS_ADVICE_BEFORE_INVOKING_METHOD, owner, name, desc); + tracing(KEY_ARTHAS_ADVICE_BEFORE_INVOKING_METHOD, owner, name, desc, lineNumber); final Label beginLabel = new Label(); final Label endLabel = new Label(); @@ -948,7 +961,7 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { mark(endLabel); // 方法调用后通知 - tracing(KEY_ARTHAS_ADVICE_AFTER_INVOKING_METHOD, owner, name, desc); + tracing(KEY_ARTHAS_ADVICE_AFTER_INVOKING_METHOD, owner, name, desc, lineNumber); goTo(finallyLabel); // } @@ -956,7 +969,7 @@ public class AdviceWeaver extends ClassVisitor implements Opcodes { // { catchException(beginLabel, endLabel, ASM_TYPE_THROWABLE); - tracing(KEY_ARTHAS_ADVICE_THROW_INVOKING_METHOD, owner, name, desc); + tracing(KEY_ARTHAS_ADVICE_THROW_INVOKING_METHOD, owner, name, desc, lineNumber); throwException(); diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/InvokeTraceable.java b/core/src/main/java/com/taobao/arthas/core/advisor/InvokeTraceable.java index a81e216b8..7690d6cd6 100644 --- a/core/src/main/java/com/taobao/arthas/core/advisor/InvokeTraceable.java +++ b/core/src/main/java/com/taobao/arthas/core/advisor/InvokeTraceable.java @@ -13,12 +13,14 @@ public interface InvokeTraceable { * @param tracingClassName 调用类名 * @param tracingMethodName 调用方法名 * @param tracingMethodDesc 调用方法描述 + * @param tracingLineNumber 执行调用行数 * @throws Throwable 通知过程出错 */ void invokeBeforeTracing( String tracingClassName, String tracingMethodName, - String tracingMethodDesc) throws Throwable; + String tracingMethodDesc, + int tracingLineNumber) throws Throwable; /** * 抛异常后跟踪 @@ -26,12 +28,14 @@ public interface InvokeTraceable { * @param tracingClassName 调用类名 * @param tracingMethodName 调用方法名 * @param tracingMethodDesc 调用方法描述 + * @param tracingLineNumber 执行调用行数 * @throws Throwable 通知过程出错 */ void invokeThrowTracing( String tracingClassName, String tracingMethodName, - String tracingMethodDesc) throws Throwable; + String tracingMethodDesc, + int tracingLineNumber) throws Throwable; /** @@ -40,12 +44,14 @@ public interface InvokeTraceable { * @param tracingClassName 调用类名 * @param tracingMethodName 调用方法名 * @param tracingMethodDesc 调用方法描述 + * @param tracingLineNumber 执行调用行数 * @throws Throwable 通知过程出错 */ void invokeAfterTracing( String tracingClassName, String tracingMethodName, - String tracingMethodDesc) throws Throwable; + String tracingMethodDesc, + int tracingLineNumber) throws Throwable; } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/AbstractTraceAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/AbstractTraceAdviceListener.java index a8ef9ae94..f5d25a610 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/AbstractTraceAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/AbstractTraceAdviceListener.java @@ -57,7 +57,8 @@ public class AbstractTraceAdviceListener extends ReflectAdviceListenerAdapter { @Override public void afterThrowing(ClassLoader loader, Class clazz, ArthasMethod method, Object target, Object[] args, Throwable throwable) throws Throwable { - threadBoundEntity.get().view.begin("throw:" + throwable.getClass().getName() + "()").end().end(); + int lineNumber = throwable.getStackTrace()[0].getLineNumber(); + threadBoundEntity.get().view.begin("throw:" + throwable.getClass().getName() + "()" + " #" + lineNumber).end().end(); final Advice advice = Advice.newForAfterThrowing(loader, clazz, method, target, args, throwable); finishing(advice); } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TraceAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TraceAdviceListener.java index f044794c0..4e50c5bf2 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TraceAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TraceAdviceListener.java @@ -20,20 +20,20 @@ public class TraceAdviceListener extends AbstractTraceAdviceListener implements * trace 会在被观测的方法体中,在每个方法调用前后插入字节码,所以方法调用开始,结束,抛异常的时候,都会回调下面的接口 */ @Override - public void invokeBeforeTracing(String tracingClassName, String tracingMethodName, String tracingMethodDesc) + public void invokeBeforeTracing(String tracingClassName, String tracingMethodName, String tracingMethodDesc, int tracingLineNumber) throws Throwable { threadBoundEntity.get().view.begin( - StringUtils.normalizeClassName(tracingClassName) + ":" + tracingMethodName + "()"); + StringUtils.normalizeClassName(tracingClassName) + ":" + tracingMethodName + "()" + " #" + tracingLineNumber); } @Override - public void invokeAfterTracing(String tracingClassName, String tracingMethodName, String tracingMethodDesc) + public void invokeAfterTracing(String tracingClassName, String tracingMethodName, String tracingMethodDesc, int tracingLineNumber) throws Throwable { threadBoundEntity.get().view.end(); } @Override - public void invokeThrowTracing(String tracingClassName, String tracingMethodName, String tracingMethodDesc) + public void invokeThrowTracing(String tracingClassName, String tracingMethodName, String tracingMethodDesc, int tracingLineNumber) throws Throwable { threadBoundEntity.get().view.end("throws Exception"); }