简体   繁体   English

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

[英]how to create a custom stacktrace in java with additional info (like parameters)?

I was assigned a task to create a custom stacktrace like output to a log file for some specified functions, but instead of just using the class and method names I would also have to output the parameters and their values. 我被分配了一个任务来创建自定义的堆栈跟踪,例如将输出输出到某些指定函数的日志文件中,但是我不仅要使用类和方法名,还必须输出参数及其值。

This is supposed to be a separate jar that could run on any java project, after. 之后,这应该是可以在任何Java项目上运行的单独的jar。

I don't even know if such thing is possible, let alone where to start. 我什至不知道这种事情是否可能,更不用说从哪里开始了。 Any help would be appreciated. 任何帮助,将不胜感激。

EDIT: there is other library that does that by using native VM api: https://github.com/cretz/stackparam it also modifies Throwable class to always print that modified stacktrace. 编辑:还有其他库通过使用本机VM API来做到这一点: https : //github.com/cretz/stackparam它还修改了Throwable类以始终打印修改后的stacktrace。

The only possible way I can think of is using agents and instrumentalization, but agent needs to be added to startup command line. 我能想到的唯一可能的方法是使用代理和工具化,但是需要将代理添加到启动命令行中。
Then I would register transformer to transform every class (remember that some basic java classes might be already loaded) using ASM library and add code to beginning of every method invocation to manually track each method class and pass it to my library that would track them: 然后,我将注册转换器以使用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 would add invocation frame to some queue and exitMethod would remove last added frame. enterMethod将调用帧添加到某些队列中,而exitMethod将删除最后添加的帧。 Note that you should have separate queue for each thread, use some Map<Thread, MyFrame> or ThreadLocal it might be good idea to use some weak references for threads. 请注意,每个线程应该有单独的队列,请使用一些Map<Thread, MyFrame>ThreadLocal ,对线程使用一些弱引用可能是个好主意。

And then you could use frames from that queue to create own stacktrace. 然后,您可以使用该队列中的帧来创建自己的堆栈跟踪。
But doing something like that might decrease performance a lot - not even just because cost of this code, but adding that to every setter/getter might cause that methods to never be inlined and affect performance even more. 但是执行类似的操作可能会大大降低性能-不仅是因为这段代码的成本,而且将其添加到每个setter / getter中可能会导致这些方法永远不会被内联,甚至会进一步影响性能。

So it is possible but I really don't recommend doing something like that. 因此有可能,但我真的不建议您这样做。
Also some other transformers added by other libraries might affect results, it might be good idea to also compare your stacktrace with original stacktrace to find any missing methods that you didn't transform - like native ones, and add them to your stacktrace but without that additional data. 另外,其他库添加的其他一些转换器也可能会影响结果,最好将您的堆栈跟踪与原始堆栈跟踪进行比较,以查找所有未转换的缺失方法(例如本机方法),然后将其添加到堆栈跟踪中,但没有这些附加数据。

If you really need to support native methods too - then you can create more advanced transformer that would add enterMethod / exitMethod before and after call to native method. 如果您确实还需要支持本机方法-那么可以创建更高级的转换器,在调用本机方法之前和之后添加enterMethod / exitMethod

Also if this is only for debugging you could use debugging API so it would only work as a debugger. 另外,如果这仅用于调试,则可以使用调试API,因此它只能用作调试器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM