作为一名系统管理员,我有时会遇到这样的情况:程序行为异常,但根本不会创建错误或创建无意义的错误消息。
过去——在java出现之前——有两种应对措施:
- 如果没有其他帮助 - RTFM ;-)
- 如果 1. 没有帮助 - 跟踪系统调用并查看发生了什么
我通常使用strace -f
Linux 来完成此任务(其他操作系统也有类似的跟踪工具)。现在,虽然这通常适用于任何老式程序,但当在爪哇-过程。有如此多的系统调用看似与任何实际操作无关,因此在这样的转储中进行搜索非常糟糕。
有没有更好的方法来做到这一点(如果源代码不可用)?
答案1
正如 ckhan 提到的,jstack
它很棒,因为它提供了 JVM 中所有活动线程的完整堆栈跟踪。可以使用 SIGQUIT 在 JVM 的 stderr 上获得相同的结果。
另一个有用的工具是jmap
它可以使用进程的 PID 从 JVM 进程中获取堆转储:
jmap -dump:file=/tmp/heap.hprof $PID
此堆转储可以加载到诸如visualvm
(现在是标准 Oracle java sdk 安装的一部分,名为 jvisualvm)之类的工具中。此外,VisualVM 可以连接到正在运行的 JVM 并显示有关 JVM 的信息,包括显示内部 CPU 使用情况、线程计数和堆使用情况的图表 - 非常适合跟踪泄漏。
另一个工具,jstat
可以在一段时间内收集 JVM 的垃圾收集统计信息,就像使用数字参数(例如vmstat 3
)运行时的 vmstat 一样。
最后,可以使用 Java 代理在加载时对所有对象的所有方法推送检测。图书馆javassist
可以帮助您轻松做到这一点。因此,添加自己的跟踪是可行的。困难的部分是找到一种方法,仅在您需要时而不是始终获取跟踪输出,这可能会减慢 JVM 的速度。有一个名为的程序dtrace
以这样的方式工作。我尝试过,但不是很成功。请注意,代理无法检测所有类,因为引导 JVM 所需的类会在代理检测之前加载,然后向这些类添加检测就为时已晚。
我的建议- 从 VisualVM 开始,看看它是否告诉您需要了解什么,因为它可以显示 JVM 的当前线程和重要统计信息。
答案2
同样,在调试 Linux 系统上出错的程序时,您可以使用类似的工具来调试系统上正在运行的 JVM。
工具#1 - jvmtop
类似于top
,您可以使用虚拟机顶部查看系统上正在运行的 JVM 中的类的情况。安装后,您可以像这样调用它:
$ jvmtop.sh
其输出的样式与该工具类似top
:
JvmTop 0.8.0 alpha amd64 8 cpus, Linux 2.6.32-27, load avg 0.12
http://code.google.com/p/jvmtop
PID MAIN-CLASS HPCUR HPMAX NHCUR NHMAX CPU GC VM USERNAME #T DL
3370 rapperSimpleApp 165m 455m 109m 176m 0.12% 0.00% S6U37 web 21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager 11m 28m 23m 130m 0.00% 0.00% S6U37 web 31
19187 m.jvmtop.JvmTop 20m 3544m 13m 130m 0.93% 0.47% S6U37 web 20
16733 artup.Bootstrap 159m 455m 166m 304m 0.12% 0.00% S6U37 web 46
工具 #2 - jvmmonitor
另一种选择是使用虚拟机监控器。 JVM Monitor 是一个与 Eclipse 集成的 Java 分析器,用于监视 Java 应用程序的 CPU、线程和内存使用情况。您可以使用它自动查找本地主机上正在运行的 JVM,也可以使用 port@host 连接到远程 JVM。
工具 #3 - visualvm
视觉虚拟机可能是调试 JVM 问题时需要使用的“工具”。它的功能集非常深入,您可以非常深入地了解其内部结构。
分析应用程序性能或分析内存分配:
获取并显示线程转储:
参考
答案3
考虑jstack
。不太匹配strace
,更像是pstack
- 模拟,但至少会给你及时的快照图片。如果需要的话,可以将它们串在一起以获得粗略的痕迹。
另请参阅这篇 SO 文章中的建议:https://stackoverflow.com/questions/1025681/call-trace-in-java
答案4
建议您尝试一下杰克游戏,这是一个 JVM 跟踪工具,允许您跟踪方法的进入和退出,而无需更改代码或重新部署。