tt command store the real method args at enter

This commit is contained in:
hengyunabc
2020-05-20 01:41:06 +08:00
parent 6d186954c6
commit 7d7b5460ad
@@ -1,28 +1,36 @@
package com.taobao.arthas.core.command.monitor200;
import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter;
import com.taobao.arthas.core.command.express.ExpressException;
import com.taobao.arthas.core.shell.command.CommandProcess;
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.util.LogUtil;
import com.taobao.arthas.core.util.ThreadLocalWatch;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.util.Date;
import static com.taobao.arthas.core.command.monitor200.TimeTunnelTable.createTable;
import static com.taobao.arthas.core.command.monitor200.TimeTunnelTable.fillTableHeader;
import static com.taobao.arthas.core.command.monitor200.TimeTunnelTable.fillTableRow;
import java.util.Date;
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.AdviceListenerAdapter;
import com.taobao.arthas.core.command.express.ExpressException;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.LogUtil;
import com.taobao.arthas.core.util.ThreadLocalWatch;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
/**
* @author beiwei30 on 30/11/2016.
* @author hengyunabc 2020-05-20
*/
public class TimeTunnelAdviceListener extends ReflectAdviceListenerAdapter {
public class TimeTunnelAdviceListener extends AdviceListenerAdapter {
private static final Logger logger = LoggerFactory.getLogger(TimeTunnelAdviceListener.class);
private final ThreadLocal<ObjectStack> argsRef = new ThreadLocal<ObjectStack>() {
@Override
protected ObjectStack initialValue() {
return new ObjectStack(512);
}
};
private TimeTunnelCommand command;
private CommandProcess process;
@@ -40,18 +48,23 @@ public class TimeTunnelAdviceListener extends ReflectAdviceListenerAdapter {
@Override
public void before(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args)
throws Throwable {
argsRef.get().push(args);
threadLocalWatch.start();
}
@Override
public void afterReturning(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args,
Object returnObject) throws Throwable {
//取出入参时的 args,因为在函数执行过程中 args可能被修改
args = (Object[]) argsRef.get().pop();
afterFinishing(Advice.newForAfterRetuning(loader, clazz, method, target, args, returnObject));
}
@Override
public void afterThrowing(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args,
Throwable throwable) {
//取出入参时的 args,因为在函数执行过程中 args可能被修改
args = (Object[]) argsRef.get().pop();
afterFinishing(Advice.newForAfterThrowing(loader, clazz, method, target, args, throwable));
}
@@ -93,4 +106,53 @@ public class TimeTunnelAdviceListener extends ReflectAdviceListenerAdapter {
abortProcess(process, command.getNumberOfLimit());
}
}
/**
*
* <pre>
* 一个特殊的stack,为了追求效率,避免扩容。
* 因为这个stack的push/pop 并不一定成对调用,比如可能push执行了,但是后面的流程被中断了,pop没有被执行。
* 如果不固定大小,一直增长的话,极端情况下可能应用有内存问题。
* 如果到达容量,pos会重置,循环存储数据。所以使用这个Stack如果在极端情况下统计的数据会不准确,只用于monitor/watch等命令的计时。
*
* </pre>
*
* @author hengyunabc 2019-11-20
*
*/
static class ObjectStack {
private Object[] array;
private int pos = 0;
private int cap;
public ObjectStack(int maxSize) {
array = new Object[maxSize];
cap = array.length;
}
public int size() {
return pos;
}
public void push(Object value) {
if (pos < cap) {
array[pos++] = value;
} else {
// if array is full, reset pos
pos = 0;
array[pos++] = value;
}
}
public Object pop() {
if (pos > 0) {
pos--;
return array[pos];
} else {
pos = cap;
pos--;
return array[pos];
}
}
}
}