Java调用序列分析

发布于 2024-11-09 16:59:01 字数 139 浏览 4 评论 0原文

我希望能够可视化给定 JVM 进程的调用序列(对哪些对象调用了哪些方法以及传递了哪些参数)。例如,可以将此信息转储到文件的工具。 有现有的工具可以做到这一点吗?如果没有,您能否给出一些关于如何做到这一点的指示?您可以建议什么解决方案(除了修改方法的字节码之外)?

I would like to be able to visualize the call sequence for a given JVM process (what methods were called on which objects and what parameters where passed). For example a tool that would dump this information to a file.
Is there an existing tool to do this? If not could you give some pointers on how this can be done? What solutions could you advise (besides modifying the bytecodes of the methods)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

记忆で 2024-11-16 16:59:01

OP 说,“Java 日志记录”不好。 “是的,但是您必须手动插入所有日志调用。对于大型项目来说这不是一个非常可行的选择,不是吗?”。

好的,您需要的是一种将自定义仪器自动插入到您的应用程序中的方法。

我们的 DMS 软件重组工具包及其 Java 前端 可用于执行此操作。 DMS 提供通用机制来解析源代码、构建 AST 和符号表、分析特殊情况的代码(树)以及对代码(树)进行转换,最终重新生成修改后的代码(从修改后的树)。 Java 前端使 DMS 能够为 Java 执行此操作; DMS还有许多其他前端语言模块。

您想要做的是编写一个 DMS 源到源转换,以使用转储参数列表值的逻辑来检测函数条目(例如,序列化它们的“toString”等效项):

tag RecordArguments(a:arguments):statements;

instrument_function_entry rule(r:type,m:identifier,a:arguments,s:stmts):method->method
   "\r \m(\a) { \s } "
   ->
   "\r \m(\a) { Call.FunctionEntry(\stringify\(\m\));\RecordArguments\(\a\); { \s } }"

empty_arguments rule () arguments -> statements
   "\RecordArguments\(\) " -> ";"

 more_arguments rule (args:arguments,a:argument) arguments -> statements
   "\RecordArguments\(\args,\a)" 
   -> "\RecordArguments\(\args\);Call.Argument(\a.toString()))"

“instrument_function_entry”规则的作用是发出一个调用来记录函数入口,并生成一系列调用来记录参数值。 “empty_arguments”规则处理没有更多参数要处理的基本情况(包括“根本没有参数”)。 “more_arguments”规则通过挑选最后一个参数来处理参数列表,生成代码来转储该参数,并生成较短的剩余参数列表以由相同规则或最终“empty_arguments”规则处理。

这应该为该方法产生什么:

 int  X3(char J, array[] X)
 { <code> }

will be

 int X3(char J, array[] X)
 {  Call.FunctionEntry("X3");
    Call.Argument(J.toString());
    Call.Argument(X.toString());
    { <code> } 
  }

您可以根据需要定义“Call”对象,以记录结果。如果您想在其中放置额外的过滤器以消除来自错误线程的数据,或者不在某个时间窗口之间或不在某个有趣事件附近的数据,您可以。这可能会大大减慢您的应用程序速度,至少如果您让仪器对应用程序中的每个函数调用执行此操作。 (更复杂的转换可以控制它们的应用位置)。

OP says, "Java logging" no good. "Yes but you have to insert manually all the log calls. Not a very viable option for a large project, is it?".

OK, what you need is a way to insert custom instrumentation automatically into your application.

Our DMS Software Reengineering Toolkit with its Java Front End could be used to do this. DMS provides generic machinery to parse source code, build ASTs and symbol tables, analyze the code (trees) for special cases, and carry out transformations on the code(trees), finally regenerating modified code (from the modified trees). The Java Front end enables DMS to do this for Java; DMS has many other front end language modules.

What you'd want to do is to write a DMS source-to-source transformation to instrument the function entry with logic to dump the parameter list values (e.g., serialize their "toString" equivalents):

tag RecordArguments(a:arguments):statements;

instrument_function_entry rule(r:type,m:identifier,a:arguments,s:stmts):method->method
   "\r \m(\a) { \s } "
   ->
   "\r \m(\a) { Call.FunctionEntry(\stringify\(\m\));\RecordArguments\(\a\); { \s } }"

empty_arguments rule () arguments -> statements
   "\RecordArguments\(\) " -> ";"

 more_arguments rule (args:arguments,a:argument) arguments -> statements
   "\RecordArguments\(\args,\a)" 
   -> "\RecordArguments\(\args\);Call.Argument(\a.toString()))"

What the "instrument_function_entry" rule does is place a call to record the function entry, and to generate a series of calls to record the argument values. The "empty_arguments" rule handles the base case of no-more-arguments to process (including "no arguments at all"). The "more_arguments" rule handle a list of arguments by picking off the last, generating code to dump that argument, and producing a shorter list of remaining argumetns to be processed by the same rule or eventually the "empty_arguments" rule.

What this should produce for the method:

 int  X3(char J, array[] X)
 { <code> }

will be

 int X3(char J, array[] X)
 {  Call.FunctionEntry("X3");
    Call.Argument(J.toString());
    Call.Argument(X.toString());
    { <code> } 
  }

You get to define the "Call" object however you like, to record the results. If you want to place extra filters in there to eliminate data from the wrong thread, or not between some time window or not near some interesting event, you can. This is likely to slow down you application a lot, at least if you let the instrumenter do this to every function call across your application. (More complex transformations can control where they are applied).

灰色世界里的红玫瑰 2024-11-16 16:59:01

我查看 Java 调用堆栈的最佳方法是通过 Eclipse 调试器。如果您只是在代码中放置断点,您将能够单步执行代码并查看调用堆栈。

The best way I have looked at the call stack for Java has been through the Eclipse debugger. If you just place break points in your code you will be able to step through the code and look at the call stack.

乖乖哒 2024-11-16 16:59:01

我认为最简单的就是使用JPDA(Java Platform Debugger Architecture)。您将必须暂停所有线程,分析,转储信息,然后恢复线程。这并不是一件小事,但乍一看应该是可能的。

I think the easiest thing is to use JPDA (Java Platform Debugger Architecture). You will have to suspend all threads, analyze, dump the info, and resume threads. It will not be trivial, but from the first look should be possible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文