support trace/watch with exist listenerId. #1207

This commit is contained in:
hengyunabc 2020-05-25 02:04:51 +08:00
parent b7414f899d
commit 4a673a79e3
9 changed files with 87 additions and 38 deletions

View File

@ -6,6 +6,8 @@ package com.taobao.arthas.core.advisor;
*/
public interface AdviceListener {
long id();
/**
* 监听器创建<br/>
* 监听器被注册时触发

View File

@ -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() {

View File

@ -19,8 +19,8 @@ public class AdviceWeaver {
private static final Logger logger = LoggerFactory.getLogger(AdviceWeaver.class);
// 通知监听器集合
private final static Map<Integer/*ADVICE_ID*/, AdviceListener> advices
= new ConcurrentHashMap<Integer, AdviceListener>();
private final static Map<Long/*ADVICE_ID*/, AdviceListener> advices
= new ConcurrentHashMap<Long, AdviceListener>();
/**
* 注册监听器
@ -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);
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -384,9 +384,8 @@ public class ProcessImpl implements Process {
private final List<String> 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<String> 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

View File

@ -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();
}