java - 在字节伙伴的 MethodDelegation 中有效地获取调用者
问题描述
我正在尝试使用字节伙伴库在我的 java 代理中构建一个调用树。要将元素添加到树中,我想使用方法委托。但是,要确定谁是任何叶子的父级,我需要知道谁调用了该方法。
我不想使用:
sun.reflect.Reflection#getCallerClass(int)
因为它在 Java 8+ 中已被弃用且不可用。另外,我试过:
public class ThreadUtil {
public static StackTraceElement getCaller() {
Instant now = Instant.now();
StackTraceElement ste = Thread.currentThread().getStackTrace()[3];
String callerClass = ste.getClassName();
String callerMethod = ste.getMethodName();
Instant now2= Instant.now();
System.out.println(Duration.between(now, now2));
return ste;
}
}
但是,它非常慢(~1 ms - 如果我有数千个电话,那就太多了)。
有没有办法在这一点上有效地让调用者(也许是一些字节好友的技巧)?
PS我的经纪人:
private static void instrument(String agentOps, Instrumentation inst) {
System.out.println("Agent");
new AgentBuilder.Default().with(new Eager())
.ignore(ElementMatchers.nameContains("com.dvelopp.agenttest"))
.type((ElementMatchers.any()))
.transform((builder, typeDescription, classLoader, module) -> builder.method(ElementMatchers.any())
.intercept(MethodDelegation.to(Interceptor.class))).installOn(inst);
}
public static class Interceptor {
@RuntimeType
public static Object intercept(@SuperCall Callable<?> zuper, @Origin Method method,
@AllArguments Object[] args, @This(optional = true) Object me) throws Exception {
System.out.println("CURRENT: " + method.getDeclaringClass().getName());
System.out.println("CALLER: " + ThreadUtil.getCaller().getClassName());
return zuper.call();
}
}
环境:Java 8
解决方案
字节码检测仅允许您生成您也可以自己编写的代码。对于您的情况,您需要创建一个我不推荐的相当侵入性的仪器:
- 检测您的目标方法以接受类型的新参数
Class
。 - 检测每个调用者以提供他们的类型作为附加参数。
更好的解决方案肯定是 Holger 在评论中建议的。使用StackWalker
,如果不可用,回退到sun.reflect.Reflection
(我知道的所有 JVM 中都存在)。
推荐阅读
- mongodb - 比较文档中的两个值并在结果中显示每行中的公共值
- tensorflow - 使用带有 cifar10 数据的 gabor 滤波器,然后堆叠过滤后的图像并将堆叠的图像馈送到神经网络
- bash - Bash 重试 - Azure CLI
- scheme - 在其过滤过程中使用局部状态突变的方案中的 Eratosthenes 筛选
- html - html 标记 nobr 在 Outlook 邮件中不起作用,试图避免换行
- vue.js - 在 Vue 中浏览不同组件时如何更改导航栏?
- python - 使用来自 REST 响应的数组中的对象
- c++ - 为什么将库与 MSVC 链接可以同时使用 `/MD` 或 `/ML`?
- javascript - Javascript 从 HTML 日期字符串中获取日期
- excel - 多个工作表名称并希望找到一种动态方法来编码需要 activesheet("sheetname") 的函数