mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
tt command store the real method args at enter
This commit is contained in:
+77
-15
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user