From 6d186954c6739e614f7cff39d708dafcf8172dc0 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Wed, 20 May 2020 01:40:12 +0800 Subject: [PATCH] remove unnecessary reflect in AdviceListenerAdapter --- .../core/advisor/AdviceListenerAdapter.java | 138 ++++++++++ .../arthas/core/advisor/ArthasMethod.java | 183 +++++++++---- .../advisor/ReflectAdviceListenerAdapter.java | 241 ------------------ .../AbstractTraceAdviceListener.java | 4 +- .../monitor200/GroovyAdviceListener.java | 4 +- .../monitor200/MonitorAdviceListener.java | 4 +- .../monitor200/StackAdviceListener.java | 4 +- .../monitor200/WatchAdviceListener.java | 4 +- 8 files changed, 275 insertions(+), 307 deletions(-) create mode 100644 core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerAdapter.java delete mode 100644 core/src/main/java/com/taobao/arthas/core/advisor/ReflectAdviceListenerAdapter.java diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerAdapter.java b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerAdapter.java new file mode 100644 index 000000000..cf1012e55 --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerAdapter.java @@ -0,0 +1,138 @@ +package com.taobao.arthas.core.advisor; + +import com.taobao.arthas.core.command.express.ExpressException; +import com.taobao.arthas.core.command.express.ExpressFactory; +import com.taobao.arthas.core.shell.command.CommandProcess; +import com.taobao.arthas.core.shell.system.Process; +import com.taobao.arthas.core.shell.system.ProcessAware; +import com.taobao.arthas.core.util.Constants; +import com.taobao.arthas.core.util.StringUtils; + +/** + * + * @author hengyunabc 2020-05-20 + * + */ +public abstract class AdviceListenerAdapter implements AdviceListener, ProcessAware { + private Process process; + + @Override + public void create() { + // default no-op + } + + @Override + public void destroy() { + // default no-op + } + + public Process getProcess() { + return process; + } + + public void setProcess(Process process) { + this.process = process; + } + + @Override + final public void before(Class clazz, String methodName, String methodDesc, Object target, Object[] args) + throws Throwable { + before(clazz.getClassLoader(), clazz, new ArthasMethod(clazz, methodName, methodDesc), target, args); + } + + @Override + final public void afterReturning(Class clazz, String methodName, String methodDesc, Object target, Object[] args, + Object returnObject) throws Throwable { + afterReturning(clazz.getClassLoader(), clazz, new ArthasMethod(clazz, methodName, methodDesc), target, args, + returnObject); + } + + @Override + final public void afterThrowing(Class clazz, String methodName, String methodDesc, Object target, Object[] args, + Throwable throwable) throws Throwable { + afterThrowing(clazz.getClassLoader(), clazz, new ArthasMethod(clazz, methodName, methodDesc), target, args, + throwable); + } + + /** + * 前置通知 + * + * @param loader 类加载器 + * @param clazz 类 + * @param method 方法 + * @param target 目标类实例 若目标为静态方法,则为null + * @param args 参数列表 + * @throws Throwable 通知过程出错 + */ + public abstract void before(ClassLoader loader, Class clazz, ArthasMethod method, Object target, Object[] args) + throws Throwable; + + /** + * 返回通知 + * + * @param loader 类加载器 + * @param clazz 类 + * @param method 方法 + * @param target 目标类实例 若目标为静态方法,则为null + * @param args 参数列表 + * @param returnObject 返回结果 若为无返回值方法(void),则为null + * @throws Throwable 通知过程出错 + */ + public abstract void afterReturning(ClassLoader loader, Class clazz, ArthasMethod method, Object target, + Object[] args, Object returnObject) throws Throwable; + + /** + * 异常通知 + * + * @param loader 类加载器 + * @param clazz 类 + * @param method 方法 + * @param target 目标类实例 若目标为静态方法,则为null + * @param args 参数列表 + * @param throwable 目标异常 + * @throws Throwable 通知过程出错 + */ + public abstract void afterThrowing(ClassLoader loader, Class clazz, ArthasMethod method, Object target, + Object[] args, Throwable throwable) throws Throwable; + + /** + * 判断条件是否满足,满足的情况下需要输出结果 + * + * @param conditionExpress 条件表达式 + * @param advice 当前的advice对象 + * @param cost 本次执行的耗时 + * @return true 如果条件表达式满足 + */ + protected boolean isConditionMet(String conditionExpress, Advice advice, double cost) throws ExpressException { + return StringUtils.isEmpty(conditionExpress) + || ExpressFactory.threadLocalExpress(advice).bind(Constants.COST_VARIABLE, cost).is(conditionExpress); + } + + protected Object getExpressionResult(String express, Advice advice, double cost) throws ExpressException { + return ExpressFactory.threadLocalExpress(advice).bind(Constants.COST_VARIABLE, cost).get(express); + } + + /** + * 是否超过了上限,超过之后,停止输出 + * + * @param limit 命令执行上限 + * @param currentTimes 当前执行次数 + * @return true 如果超过或者达到了上限 + */ + protected boolean isLimitExceeded(int limit, int currentTimes) { + return currentTimes >= limit; + } + + /** + * 超过次数上限,则不再输出,命令终止 + * + * @param process the process to be aborted + * @param limit the limit to be printed + */ + protected void abortProcess(CommandProcess process, int limit) { + process.write("Command execution times exceed limit: " + limit + + ", so command will exit. You can set it with -n option.\n"); + process.end(); + } + +} diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/ArthasMethod.java b/core/src/main/java/com/taobao/arthas/core/advisor/ArthasMethod.java index cd8f60fdf..9339e6c6e 100644 --- a/core/src/main/java/com/taobao/arthas/core/advisor/ArthasMethod.java +++ b/core/src/main/java/com/taobao/arthas/core/advisor/ArthasMethod.java @@ -4,43 +4,111 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import org.objectweb.asm.Type; + +import com.taobao.arthas.core.util.StringUtils; + /** - * Arthas封装的方法
- * 主要用来封装构造函数cinit/init/method - * Created by vlinux on 15/5/24. + * + * 主要用于 tt 命令重放使用 + * + * @author vlinux on 15/5/24 + * @author hengyunabc 2020-05-20 + * */ public class ArthasMethod { + private final Class clazz; + private final String methodName; + private final String methodDesc; - private final int type; - private final Constructor constructor; - private final Method method; + private Constructor constructor; + private Method method; - /* - * 构造方法 - */ - private static final int TYPE_INIT = 1 << 1; + private void initMethod() { + if (constructor != null || method != null) { + return; + } - /* - * 普通方法 - */ - private static final int TYPE_METHOD = 1 << 2; + try { + ClassLoader loader = this.clazz.getClassLoader(); + final org.objectweb.asm.Type asmType = org.objectweb.asm.Type.getMethodType(methodDesc); + + // to arg types + final Class[] argsClasses = new Class[asmType.getArgumentTypes().length]; + for (int index = 0; index < argsClasses.length; index++) { + // asm class descriptor to jvm class + final Class argumentClass; + final Type argumentAsmType = asmType.getArgumentTypes()[index]; + switch (argumentAsmType.getSort()) { + case Type.BOOLEAN: { + argumentClass = boolean.class; + break; + } + case Type.CHAR: { + argumentClass = char.class; + break; + } + case Type.BYTE: { + argumentClass = byte.class; + break; + } + case Type.SHORT: { + argumentClass = short.class; + break; + } + case Type.INT: { + argumentClass = int.class; + break; + } + case Type.FLOAT: { + argumentClass = float.class; + break; + } + case Type.LONG: { + argumentClass = long.class; + break; + } + case Type.DOUBLE: { + argumentClass = double.class; + break; + } + case Type.ARRAY: { + argumentClass = toClass(loader, argumentAsmType.getInternalName()); + break; + } + case Type.VOID: { + argumentClass = void.class; + break; + } + case Type.OBJECT: + case Type.METHOD: + default: { + argumentClass = toClass(loader, argumentAsmType.getClassName()); + break; + } + } + + argsClasses[index] = argumentClass; + } + + if ("".equals(this.methodName)) { + this.constructor = clazz.getDeclaredConstructor(argsClasses); + ; + } else { + this.method = clazz.getDeclaredMethod(methodName, argsClasses); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } - /** - * 是否构造方法 - * - * @return true/false - */ - public boolean isInit() { - return (TYPE_INIT & type) == TYPE_INIT; } - /** - * 是否普通方法 - * - * @return true/false - */ - public boolean isMethod() { - return (TYPE_METHOD & type) == TYPE_METHOD; + private Class toClass(ClassLoader loader, String className) throws ClassNotFoundException { + return Class.forName(StringUtils.normalizeClassName(className), true, toClassLoader(loader)); + } + + private ClassLoader toClassLoader(ClassLoader loader) { + return null != loader ? loader : ArthasMethod.class.getClassLoader(); } /** @@ -49,50 +117,53 @@ public class ArthasMethod { * @return 返回方法名称 */ public String getName() { - return isInit() - ? "" - : method.getName(); + return this.methodName; } @Override public String toString() { - return isInit() - ? constructor.toString() - : method.toString(); + initMethod(); + if (constructor != null) { + return constructor.toString(); + } else if (method != null) { + return method.toString(); + } + return "ERROR_METHOD"; } public boolean isAccessible() { - return isInit() - ? constructor.isAccessible() - : method.isAccessible(); + initMethod(); + if (this.method != null) { + return method.isAccessible(); + } else if (this.constructor != null) { + return constructor.isAccessible(); + } + return false; } public void setAccessible(boolean accessFlag) { - if (isInit()) { + initMethod(); + if (constructor != null) { constructor.setAccessible(accessFlag); - } else { + } else if (method != null) { method.setAccessible(accessFlag); } } - public Object invoke(Object target, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException { - return isInit() - ? constructor.newInstance(args) - : method.invoke(target, args); - } - - private ArthasMethod(int type, Constructor constructor, Method method) { - this.type = type; - this.constructor = constructor; - this.method = method; - } - - public static ArthasMethod newInit(Constructor constructor) { - return new ArthasMethod(TYPE_INIT, constructor, null); + public Object invoke(Object target, Object... args) + throws IllegalAccessException, InvocationTargetException, InstantiationException { + initMethod(); + if (method != null) { + return method.invoke(target, args); + } else if (this.constructor != null) { + return constructor.newInstance(args); + } + return null; } - public static ArthasMethod newMethod(Method method) { - return new ArthasMethod(TYPE_METHOD, null, method); + public ArthasMethod(Class clazz, String methodName, String methodDesc) { + this.clazz = clazz; + this.methodName = methodName; + this.methodDesc = methodDesc; } - } diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/ReflectAdviceListenerAdapter.java b/core/src/main/java/com/taobao/arthas/core/advisor/ReflectAdviceListenerAdapter.java deleted file mode 100644 index 32fa24208..000000000 --- a/core/src/main/java/com/taobao/arthas/core/advisor/ReflectAdviceListenerAdapter.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.taobao.arthas.core.advisor; - -import com.taobao.arthas.core.command.express.ExpressException; -import com.taobao.arthas.core.command.express.ExpressFactory; -import com.taobao.arthas.core.shell.command.CommandProcess; -import com.taobao.arthas.core.shell.system.Process; -import com.taobao.arthas.core.shell.system.ProcessAware; -import com.taobao.arthas.core.util.ArthasCheckUtils; -import com.taobao.arthas.core.util.Constants; -import com.taobao.arthas.core.util.StringUtils; -import org.objectweb.asm.Type; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -/** - * 反射通知适配器
- * 通过反射拿到对应的Class/Method类,而不是原始的ClassName/MethodName - * 当然性能开销要比普通监听器高许多 - */ -public abstract class ReflectAdviceListenerAdapter implements AdviceListener , ProcessAware{ - private Process process; - - @Override - public void create() { - // default no-op - } - - @Override - public void destroy() { - // default no-op - } - - public Process getProcess() { - return process; - } - - public void setProcess(Process process) { - this.process = process; - } - - private ClassLoader toClassLoader(ClassLoader loader) { - return null != loader - ? loader - : AdviceListener.class.getClassLoader(); - } - - private Class toClass(ClassLoader loader, String className) throws ClassNotFoundException { - return Class.forName(StringUtils.normalizeClassName(className), true, toClassLoader(loader)); - } - - private ArthasMethod toMethod(ClassLoader loader, Class clazz, String methodName, String methodDesc) - throws ClassNotFoundException, NoSuchMethodException { - final org.objectweb.asm.Type asmType = org.objectweb.asm.Type.getMethodType(methodDesc); - - // to arg types - final Class[] argsClasses = new Class[asmType.getArgumentTypes().length]; - for (int index = 0; index < argsClasses.length; index++) { - // asm class descriptor to jvm class - final Class argumentClass; - final Type argumentAsmType = asmType.getArgumentTypes()[index]; - switch (argumentAsmType.getSort()) { - case Type.BOOLEAN: { - argumentClass = boolean.class; - break; - } - case Type.CHAR: { - argumentClass = char.class; - break; - } - case Type.BYTE: { - argumentClass = byte.class; - break; - } - case Type.SHORT: { - argumentClass = short.class; - break; - } - case Type.INT: { - argumentClass = int.class; - break; - } - case Type.FLOAT: { - argumentClass = float.class; - break; - } - case Type.LONG: { - argumentClass = long.class; - break; - } - case Type.DOUBLE: { - argumentClass = double.class; - break; - } - case Type.ARRAY: { - argumentClass = toClass(loader, argumentAsmType.getInternalName()); - break; - } - case Type.VOID: { - argumentClass = void.class; - break; - } - case Type.OBJECT: - case Type.METHOD: - default: { - argumentClass = toClass(loader, argumentAsmType.getClassName()); - break; - } - } - - argsClasses[index] = argumentClass; - } - - // to method or constructor - if (ArthasCheckUtils.isEquals(methodName, "")) { - return ArthasMethod.newInit(toConstructor(clazz, argsClasses)); - } else { - return ArthasMethod.newMethod(toMethod(clazz, methodName, argsClasses)); - } - } - - private Method toMethod(Class clazz, String methodName, Class[] argClasses) throws NoSuchMethodException { - return clazz.getDeclaredMethod(methodName, argClasses); - } - - private Constructor toConstructor(Class clazz, Class[] argClasses) throws NoSuchMethodException { - return clazz.getDeclaredConstructor(argClasses); - } - - - @Override - final public void before( - Class clazz, String methodName, String methodDesc, - Object target, Object[] args) throws Throwable { - before(clazz.getClassLoader(), clazz, toMethod(clazz.getClassLoader(), clazz, methodName, methodDesc), target, args); - } - - @Override - final public void afterReturning( - Class clazz, String methodName, String methodDesc, - Object target, Object[] args, Object returnObject) throws Throwable { - afterReturning(clazz.getClassLoader(), clazz, toMethod(clazz.getClassLoader(), clazz, methodName, methodDesc), target, args, returnObject); - } - - @Override - final public void afterThrowing( - Class clazz, String methodName, String methodDesc, - Object target, Object[] args, Throwable throwable) throws Throwable { - afterThrowing(clazz.getClassLoader(), clazz, toMethod(clazz.getClassLoader(), clazz, methodName, methodDesc), target, args, throwable); - } - - - /** - * 前置通知 - * - * @param loader 类加载器 - * @param clazz 类 - * @param method 方法 - * @param target 目标类实例 - * 若目标为静态方法,则为null - * @param args 参数列表 - * @throws Throwable 通知过程出错 - */ - public abstract void before( - ClassLoader loader, Class clazz, ArthasMethod method, - Object target, Object[] args) throws Throwable; - - /** - * 返回通知 - * - * @param loader 类加载器 - * @param clazz 类 - * @param method 方法 - * @param target 目标类实例 - * 若目标为静态方法,则为null - * @param args 参数列表 - * @param returnObject 返回结果 - * 若为无返回值方法(void),则为null - * @throws Throwable 通知过程出错 - */ - public abstract void afterReturning( - ClassLoader loader, Class clazz, ArthasMethod method, - Object target, Object[] args, - Object returnObject) throws Throwable; - - /** - * 异常通知 - * - * @param loader 类加载器 - * @param clazz 类 - * @param method 方法 - * @param target 目标类实例 - * 若目标为静态方法,则为null - * @param args 参数列表 - * @param throwable 目标异常 - * @throws Throwable 通知过程出错 - */ - public abstract void afterThrowing( - ClassLoader loader, Class clazz, ArthasMethod method, - Object target, Object[] args, - Throwable throwable) throws Throwable; - - - /** - * 判断条件是否满足,满足的情况下需要输出结果 - * @param conditionExpress 条件表达式 - * @param advice 当前的advice对象 - * @param cost 本次执行的耗时 - * @return true 如果条件表达式满足 - */ - protected boolean isConditionMet(String conditionExpress, Advice advice, double cost) throws ExpressException { - return StringUtils.isEmpty(conditionExpress) || - ExpressFactory.threadLocalExpress(advice).bind(Constants.COST_VARIABLE, cost).is(conditionExpress); - } - - protected Object getExpressionResult(String express, Advice advice, double cost) throws ExpressException { - return ExpressFactory.threadLocalExpress(advice) - .bind(Constants.COST_VARIABLE, cost).get(express); - } - - /** - * 是否超过了上限,超过之后,停止输出 - * @param limit 命令执行上限 - * @param currentTimes 当前执行次数 - * @return true 如果超过或者达到了上限 - */ - protected boolean isLimitExceeded(int limit, int currentTimes) { - return currentTimes >= limit; - } - - /** - * 超过次数上限,则不再输出,命令终止 - * @param process the process to be aborted - * @param limit the limit to be printed - */ - protected void abortProcess(CommandProcess process, int limit) { - process.write("Command execution times exceed limit: " + limit + ", so command will exit. You can set it with -n option.\n"); - process.end(); - } - -} 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 ce2e784f7..069d4e0f0 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 @@ -4,7 +4,7 @@ import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.taobao.arthas.core.advisor.Advice; import com.taobao.arthas.core.advisor.ArthasMethod; -import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter; +import com.taobao.arthas.core.advisor.AdviceListenerAdapter; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.util.LogUtil; import com.taobao.arthas.core.util.ThreadLocalWatch; @@ -12,7 +12,7 @@ import com.taobao.arthas.core.util.ThreadLocalWatch; /** * @author ralf0131 2017-01-06 16:02. */ -public class AbstractTraceAdviceListener extends ReflectAdviceListenerAdapter { +public class AbstractTraceAdviceListener extends AdviceListenerAdapter { private static final Logger logger = LoggerFactory.getLogger(AbstractTraceAdviceListener.class); protected final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch(); protected TraceCommand command; diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/GroovyAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/GroovyAdviceListener.java index 8b97ca997..1f42f536d 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/GroovyAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/GroovyAdviceListener.java @@ -1,6 +1,6 @@ package com.taobao.arthas.core.command.monitor200; -import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter; +import com.taobao.arthas.core.advisor.AdviceListenerAdapter; import com.taobao.arthas.core.command.ScriptSupportCommand; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.advisor.Advice; @@ -11,7 +11,7 @@ import com.taobao.arthas.core.advisor.ArthasMethod; * @author beiwei30 on 01/12/2016. */ @Deprecated -public class GroovyAdviceListener extends ReflectAdviceListenerAdapter { +public class GroovyAdviceListener extends AdviceListenerAdapter { private ScriptSupportCommand.ScriptListener scriptListener; private ScriptSupportCommand.Output output; diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorAdviceListener.java index eea9f8640..d92498fa8 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorAdviceListener.java @@ -1,6 +1,6 @@ package com.taobao.arthas.core.command.monitor200; -import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter; +import com.taobao.arthas.core.advisor.AdviceListenerAdapter; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.advisor.ArthasMethod; import com.taobao.arthas.core.util.ThreadLocalWatch; @@ -66,7 +66,7 @@ import static com.taobao.text.ui.Element.label; * * @author beiwei30 on 28/11/2016. */ -class MonitorAdviceListener extends ReflectAdviceListenerAdapter { +class MonitorAdviceListener extends AdviceListenerAdapter { // 输出定时任务 private Timer timer; // 监控数据 diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/StackAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/StackAdviceListener.java index a5f73aa7c..783d8b767 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/StackAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/StackAdviceListener.java @@ -1,6 +1,6 @@ package com.taobao.arthas.core.command.monitor200; -import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter; +import com.taobao.arthas.core.advisor.AdviceListenerAdapter; import com.taobao.arthas.core.shell.command.CommandProcess; import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; @@ -14,7 +14,7 @@ import com.taobao.arthas.core.util.ThreadUtil; /** * @author beiwei30 on 29/11/2016. */ -public class StackAdviceListener extends ReflectAdviceListenerAdapter { +public class StackAdviceListener extends AdviceListenerAdapter { private static final Logger logger = LoggerFactory.getLogger(StackAdviceListener.class); private final ThreadLocal stackThreadLocal = new ThreadLocal(); diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java index a516fe59d..fe1c48ec3 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java @@ -4,7 +4,7 @@ import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.taobao.arthas.core.advisor.Advice; import com.taobao.arthas.core.advisor.ArthasMethod; -import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter; +import com.taobao.arthas.core.advisor.AdviceListenerAdapter; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.util.DateUtils; import com.taobao.arthas.core.util.LogUtil; @@ -15,7 +15,7 @@ import com.taobao.arthas.core.view.ObjectView; /** * @author beiwei30 on 29/11/2016. */ -class WatchAdviceListener extends ReflectAdviceListenerAdapter { +class WatchAdviceListener extends AdviceListenerAdapter { private static final Logger logger = LoggerFactory.getLogger(WatchAdviceListener.class); private final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch();