3

根据我的理解,Java 线程转储是所有线程的转储,描述了 JVM 中的每个线程正在做什么或每个线程在特定时间点的状态。同样,内存转储表示特定时间点内存的健康状况。

是否有任何工具提供一种方法来获取一个小时或更长时间的内存或线程转储,以便如果我想分析一个小时的状态,我可以做到这一点?

我在 jconsole、jvisualvm 或 dynatrace 中看不到任何方法。也许有办法,但我没有找到它?

4

4 回答 4

2

如果您想要定期转储内存/线程状态,我不知道有任何工具可以做到这一点,但编写自己的实现应该很容易。

对于线程转储,您可以使用jstackjhat用于堆转储。两者都是标准 JDK 的一部分。

请记住,保存大量堆转储很容易耗尽所有磁盘内存。另外,我不确定长时间的线程转储是否有用。据我所知,它们通常用于在特定时间范围内检查堆栈以查找错误/死锁等。

于 2015-12-10T13:20:32.040 回答
2

至于内存转储:定期转储内存需要一个非常非常大且非常非常快的文件系统。所以不,我不建议这样做。最好根据 gc 活动或其他条件定义一些触发器。

关于堆栈跟踪:如果您面临竞争条件,您的(大量多线程?)应用程序对所有用户冻结或减慢的阶段,我发现收集一些(3-5)个线程转储(3 到 5 个)很有帮助定期偏移秒数(我们从 5 分钟开始,随着系统变得更加稳定,将其缩短到 30m),然后将这些快照相互比较,以确定可能的干扰。

虽然第一次迭代涉及 jstack,但后来演变为基于 JMX 的对 Java 应用程序的访问并同时提取数据库锁定信息。

所以你的问题可以用衷心的方式回答:“这取决于”。OutOfMemoryError仅当您看到s时才应提取内存转储。在可能存在高流量/冻结/线程拥塞的情况下,线程转储可能很有用。

于 2015-12-10T14:42:21.967 回答
0

您可以使用 Javamelody,但您需要将其“添加”到您的应用程序中。

https://github.com/javamelody/javamelody/

它允许您监视您的应用程序并查看历史记录,以及生成转储(但我认为它不能在过去的两个事件之间为您提供转储)

于 2015-12-10T13:32:24.027 回答
0

如果您想要完整的内存转储,那么您必须进行堆转储(jmap -F -dump:live,format=b,file=),这在生产系统中不推荐(Jan 已经指出)。但是,还有其他方法可以在不影响生产系统性能的情况下定期监控内存使用情况:

  1. jstat -gc Process_ID 300s

这将每五分钟捕获一次总体内存使用情况和垃圾收集详细信息。但是,它不会告诉您哪个对象正在消耗多少内存等(由堆转储捕获)。但是,如果存在内存泄漏,您将能够随着时间的推移找出答案。

  1. jmap -histo Process_ID

这将为应用程序生成直方图信息。编写一个脚本,每 _ 分钟调用一次。

如果 #1 和 #2 显示内存泄漏的症状,那么只进行堆转储,但它可能会“挂起”您的应用程序,您可能必须在捕获堆转储后重新启动它。

就线程转储而言,如果您想定期监控线程状态,您可以使用以下内容。我熟悉他们每 5 分钟执行一次并存储过去 7 天数据的应用程序。

jstack Process_ID

或(使用 Java 8)

jcmd Process_ID Thread.print

在异常情况下,您始终可以每 10 秒捕获 5/6 个线程转储。

或者,如果您(或您的公司)负担得起并且想要定期关注系统,您可能会寻找New Relic类型的软件。

于 2015-12-13T05:45:49.843 回答