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);
+ 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;
}
- private ArthasMethod(int type, Constructor> constructor, Method method) {
- this.type = type;
- this.constructor = constructor;
- this.method = method;
+ public ArthasMethod(Class> clazz, String methodName, String methodDesc) {
+ this.clazz = clazz;
+ this.methodName = methodName;
+ this.methodDesc = methodDesc;
}
-
- public static ArthasMethod newInit(Constructor> constructor) {
- return new ArthasMethod(TYPE_INIT, constructor, null);
- }
-
- public static ArthasMethod newMethod(Method method) {
- return new ArthasMethod(TYPE_METHOD, null, method);
- }
-
}
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();