我被分配了一个任务来创建自定义的堆栈跟踪,例如输出到某些指定功能的日志文件中,但是我不仅要使用类和方法名,还必须输出参数及其值。
这应该是一个单独的jar,之后可以在任何Java项目上运行。
我什至不知道这样的事情是否可能,更不用说从哪里开始了。 任何帮助将不胜感激。
答案 0 :(得分:0)
编辑:还有其他库通过使用本机VM api来做到这一点:https://github.com/cretz/stackparam还会修改Throwable类以始终打印修改后的stacktrace。
我能想到的唯一可能的方法是使用代理和工具化,但是需要将代理添加到启动命令行中。
然后,我将注册转换器以使用ASM库转换每个类(记住一些基本的Java类可能已经加载),并将代码添加到每个方法调用的开头,以手动跟踪每个方法类并将其传递给将跟踪它们的我的库:
// note that parameters names might not exist in runtime if code was compiled without a flag to include them.
public void doSomething(String name, int something) {
MyLib.enterMethod(ThisClass.class, new MethodSignature(void.class, String.class, int.class), new Argument("name", name), new Argument("something", something));
try {
// original code
} finally { // so we don't need to care about return in the middle of original code or exceptions
MyLib.exitMethod();
}
}
enterMethod
将调用帧添加到某个队列中,而exitMethod
将删除最后添加的帧。请注意,每个线程应该有单独的队列,使用一些Map<Thread, MyFrame>
或ThreadLocal
,最好对线程使用一些弱引用。
然后您可以使用该队列中的帧创建自己的堆栈跟踪。
但是,这样做可能会大大降低性能-不仅是因为这段代码的成本,而是将其添加到每个setter / getter中可能会导致这些方法永远不会被内联,甚至会进一步影响性能。
因此有可能,但我真的不建议您这样做。
另外,其他库添加的其他一些转换器也可能会影响结果,最好将您的堆栈跟踪与原始堆栈跟踪进行比较,以查找所有未转换的缺失方法(例如本机方法),然后将其添加到堆栈跟踪中,但没有这些其他数据。
如果您确实也需要支持本机方法-那么可以创建更高级的转换器,在调用本机方法之前和之后添加enterMethod
/ exitMethod
。
如果这仅用于调试,则可以使用调试API,因此它只能用作调试器。