如何在带有附加信息(如参数)的Java中创建自定义stacktrace?

时间:2018-08-23 10:59:31

标签: java function jar stack-trace

我被分配了一个任务来创建自定义的堆栈跟踪,例如输出到某些指定功能的日志文件中,但是我不仅要使用类和方法名,还必须输出参数及其值。

这应该是一个单独的jar,之后可以在任何Java项目上运行。

我什至不知道这样的事情是否可能,更不用说从哪里开始了。 任何帮助将不胜感激。

1 个答案:

答案 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,因此它只能用作调试器。