From 4a673a79e3154a82f258ccc68f72a26d91674933 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Mon, 25 May 2020 02:04:51 +0800 Subject: [PATCH] support trace/watch with exist listenerId. #1207 --- .../arthas/core/advisor/AdviceListener.java | 2 + .../core/advisor/AdviceListenerAdapter.java | 9 +++++ .../arthas/core/advisor/AdviceWeaver.java | 30 +++++++-------- .../taobao/arthas/core/advisor/Enhancer.java | 3 +- .../command/monitor200/EnhancerCommand.java | 24 +++++++++++- .../core/command/monitor200/WatchCommand.java | 2 +- .../core/shell/command/CommandProcess.java | 3 +- .../core/shell/system/impl/ProcessImpl.java | 38 +++++++++++-------- .../core/util/affect/EnhancerAffect.java | 14 ++++++- 9 files changed, 87 insertions(+), 38 deletions(-) diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListener.java b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListener.java index bcfefee0e..fa7511b19 100644 --- a/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListener.java @@ -6,6 +6,8 @@ package com.taobao.arthas.core.advisor; */ public interface AdviceListener { + long id(); + /** * 监听器创建
* 监听器被注册时触发 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 index cf1012e55..21315bac3 100644 --- a/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerAdapter.java +++ b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerAdapter.java @@ -1,5 +1,7 @@ package com.taobao.arthas.core.advisor; +import java.util.concurrent.atomic.AtomicLong; + import com.taobao.arthas.core.command.express.ExpressException; import com.taobao.arthas.core.command.express.ExpressFactory; import com.taobao.arthas.core.shell.command.CommandProcess; @@ -14,7 +16,14 @@ import com.taobao.arthas.core.util.StringUtils; * */ public abstract class AdviceListenerAdapter implements AdviceListener, ProcessAware { + private static final AtomicLong ID_GENERATOR = new AtomicLong(0); private Process process; + private long id = ID_GENERATOR.addAndGet(1); + + @Override + public long id() { + return id; + } @Override public void create() { 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 2b607da6f..aadcbca68 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 @@ -19,8 +19,8 @@ public class AdviceWeaver { private static final Logger logger = LoggerFactory.getLogger(AdviceWeaver.class); // 通知监听器集合 - private final static Map advices - = new ConcurrentHashMap(); + private final static Map advices + = new ConcurrentHashMap(); /** * 注册监听器 @@ -28,13 +28,13 @@ public class AdviceWeaver { * @param adviceId 通知ID * @param listener 通知监听器 */ - public static void reg(int adviceId, AdviceListener listener) { + public static void reg(AdviceListener listener) { // 触发监听器创建 listener.create(); // 注册监听器 - advices.put(adviceId, listener); + advices.put(listener.id(), listener); } /** @@ -42,28 +42,28 @@ public class AdviceWeaver { * * @param adviceId 通知ID */ - public static void unReg(int adviceId) { - - // 注销监听器 - final AdviceListener listener = advices.remove(adviceId); - - // 触发监听器销毁 + public static void unReg(AdviceListener listener) { if (null != listener) { + // 注销监听器 + advices.remove(listener.id()); + + // 触发监听器销毁 listener.destroy(); } - } + public static AdviceListener listener(long id) { + return advices.get(id); + } /** * 恢复监听 * - * @param adviceId 通知ID * @param listener 通知监听器 */ - public static void resume(int adviceId, AdviceListener listener) { + public static void resume(AdviceListener listener) { // 注册监听器 - advices.put(adviceId, listener); + advices.put(listener.id(), listener); } /** @@ -71,7 +71,7 @@ public class AdviceWeaver { * * @param adviceId 通知ID */ - public static AdviceListener suspend(int adviceId) { + public static AdviceListener suspend(long adviceId) { // 注销监听器 return advices.remove(adviceId); } diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java b/core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java index 57fbdee98..8e97bc17e 100644 --- a/core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java +++ b/core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java @@ -94,7 +94,8 @@ public class Enhancer implements ClassFileTransformer { this.skipJDKTrace = skipJDKTrace; this.classNameMatcher = classNameMatcher; this.methodNameMatcher = methodNameMatcher; - this.affect = new EnhancerAffect();; + this.affect = new EnhancerAffect(); + affect.setListenerId(listener.id()); } public static class SpyInterceptor { diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/EnhancerCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/EnhancerCommand.java index b2de2d3fe..2b88f69de 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/EnhancerCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/EnhancerCommand.java @@ -8,6 +8,7 @@ import java.util.List; import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.taobao.arthas.core.advisor.AdviceListener; +import com.taobao.arthas.core.advisor.AdviceWeaver; import com.taobao.arthas.core.advisor.Enhancer; import com.taobao.arthas.core.advisor.InvokeTraceable; import com.taobao.arthas.core.shell.cli.Completion; @@ -21,6 +22,8 @@ import com.taobao.arthas.core.util.Constants; import com.taobao.arthas.core.util.LogUtil; import com.taobao.arthas.core.util.affect.EnhancerAffect; import com.taobao.arthas.core.util.matcher.Matcher; +import com.taobao.middleware.cli.annotations.Description; +import com.taobao.middleware.cli.annotations.Option; /** * @author beiwei30 on 29/11/2016. @@ -35,6 +38,14 @@ public abstract class EnhancerCommand extends AnnotatedCommand { protected Matcher classNameMatcher; protected Matcher methodNameMatcher; + protected long listenerId; + + @Option(longName = "listenerId") + @Description("The special listenerId") + public void setListenerId(long listenerId) { + this.listenerId = listenerId; + } + /** * 类名匹配 * @@ -56,6 +67,15 @@ public abstract class EnhancerCommand extends AnnotatedCommand { */ protected abstract AdviceListener getAdviceListener(CommandProcess process); + AdviceListener getAdviceListenerWithId(CommandProcess process) { + if (listenerId != 0) { + AdviceListener listener = AdviceWeaver.listener(listenerId); + if (listener != null) { + return listener; + } + } + return getAdviceListener(process); + } @Override public void process(final CommandProcess process) { // ctrl-C support @@ -99,7 +119,7 @@ public abstract class EnhancerCommand extends AnnotatedCommand { int lock = session.getLock(); try { Instrumentation inst = session.getInstrumentation(); - AdviceListener listener = getAdviceListener(process); + AdviceListener listener = getAdviceListenerWithId(process); if (listener == null) { warn(process, "advice listener is null"); return; @@ -111,7 +131,7 @@ public abstract class EnhancerCommand extends AnnotatedCommand { Enhancer enhancer = new Enhancer(listener, listener instanceof InvokeTraceable, skipJDKTrace, getClassNameMatcher(), getMethodNameMatcher()); // 注册通知监听器 - process.register(lock, listener, enhancer); + process.register(listener, enhancer); EnhancerAffect effect = enhancer.enhance(inst); if (effect.cCnt() == 0 || effect.mCnt() == 0) { diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java index 785894d81..7126f1181 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java @@ -42,7 +42,7 @@ public class WatchCommand extends EnhancerCommand { private Integer sizeLimit = 10 * 1024 * 1024; private boolean isRegEx = false; private int numberOfLimit = 100; - + @Argument(index = 0, argName = "class-pattern") @Description("The full qualified class name you want to watch") public void setClassPattern(String classPattern) { diff --git a/core/src/main/java/com/taobao/arthas/core/shell/command/CommandProcess.java b/core/src/main/java/com/taobao/arthas/core/shell/command/CommandProcess.java index b3a12dbef..0c2694ff8 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/command/CommandProcess.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/command/CommandProcess.java @@ -123,10 +123,9 @@ public interface CommandProcess extends Tty { /** * Register listener * - * @param lock the lock for enhance class * @param listener */ - void register(int lock, AdviceListener listener, ClassFileTransformer transformer); + void register(AdviceListener listener, ClassFileTransformer transformer); /** * Unregister listener diff --git a/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java b/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java index b28b7875a..b09711172 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java @@ -384,9 +384,8 @@ public class ProcessImpl implements Process { private final List args2; private final Tty tty; private final CommandLine commandLine; - private int enhanceLock = -1; private AtomicInteger times = new AtomicInteger(); - private AdviceListener suspendedListener = null; + private AdviceListener listener = null; private ClassFileTransformer transformer; public CommandProcessImpl(Process process, List args2, Tty tty, CommandLine commandLine) { @@ -528,13 +527,15 @@ public class ProcessImpl implements Process { } @Override - public void register(int enhanceLock, AdviceListener listener, ClassFileTransformer transformer) { - this.enhanceLock = enhanceLock; - + public void register(AdviceListener listener, ClassFileTransformer transformer) { if (listener instanceof ProcessAware) { - ((ProcessAware) listener).setProcess(this.process); + ProcessAware processAware = (ProcessAware) listener; + // listener 有可能是其它 command 创建的 + if(processAware.getProcess() == null) { + processAware.setProcess(this.process); + } } - AdviceWeaver.reg(enhanceLock, listener); + AdviceWeaver.reg(listener); this.transformer = transformer; } @@ -545,22 +546,29 @@ public class ProcessImpl implements Process { ArthasBootstrap.getInstance().getTransformerManager().removeTransformer(transformer); } - AdviceWeaver.unReg(enhanceLock); + if (listener instanceof ProcessAware) { + // listener有可能其它 command 创建的,所以不能unRge + if (this.process.equals(((ProcessAware) listener).getProcess())) { + AdviceWeaver.unReg(listener); + } + } else { + AdviceWeaver.unReg(listener); + } } @Override public void resume() { - if (this.enhanceLock >= 0 && suspendedListener != null) { - AdviceWeaver.resume(enhanceLock, suspendedListener); - suspendedListener = null; - } +// if (suspendedListener != null) { +// AdviceWeaver.resume(suspendedListener); +// suspendedListener = null; +// } } @Override public void suspend() { - if (this.enhanceLock >= 0) { - suspendedListener = AdviceWeaver.suspend(enhanceLock); - } +// if (this.enhanceLock >= 0) { +// suspendedListener = AdviceWeaver.suspend(enhanceLock); +// } } @Override diff --git a/core/src/main/java/com/taobao/arthas/core/util/affect/EnhancerAffect.java b/core/src/main/java/com/taobao/arthas/core/util/affect/EnhancerAffect.java index a1bfb9e36..4189e708e 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/affect/EnhancerAffect.java +++ b/core/src/main/java/com/taobao/arthas/core/util/affect/EnhancerAffect.java @@ -22,6 +22,7 @@ public final class EnhancerAffect extends Affect { private final AtomicInteger cCnt = new AtomicInteger(); private final AtomicInteger mCnt = new AtomicInteger(); private ClassFileTransformer transformer; + private long listenerId; /** * dumpClass的文件存放集合 */ @@ -92,6 +93,14 @@ public final class EnhancerAffect extends Affect { this.transformer = transformer; } + public long getListenerId() { + return listenerId; + } + + public void setListenerId(long listenerId) { + this.listenerId = listenerId; + } + @Override public String toString() { final StringBuilder infoSB = new StringBuilder(); @@ -108,10 +117,11 @@ public final class EnhancerAffect extends Affect { infoSB.append("[Affect method: ").append(method).append("]\n"); } } - infoSB.append(format("Affect(class count:%d , method count:%d) cost in %s ms.", + infoSB.append(format("Affect(class count: %d , method count: %d) cost in %s ms, listenerId: %d", cCnt(), mCnt(), - cost())); + cost(), + listenerId)); return infoSB.toString(); }