根据我的理解,Java线程转储是所有线程的转储,描述了JVM中每个线程正在做什么或每个线程的状态 在特定的时间点。类似地,内存转储表示特定时间点的内存运行状况。
是否有任何工具提供一种方法来获取一小时或更长时间的内存或线程转储,这样如果我想分析一小时的状态,我可以这样做吗?
我在jconsole,jvisualvm或dynatrace中没有看到任何方法。也许有办法,但我找不到它?
答案 0 :(得分:2)
如果您想要的是定期转储内存/线程状态,我不知道任何可以做到这一点的工具,但编写自己的实现应该很容易。
对于线程转储,您可以使用jstack和jhat进行堆转储。两者都是标准JDK的一部分。
请记住,节省大量堆转储很容易耗尽所有磁盘内存。此外,我不确定长时间的线程转储是否有用。据我所知,它们通常用于在特定时间范围内检查堆栈以查找错误/死锁等。
答案 1 :(得分:2)
至于内存转储:定期转储内存需要一个非常非常非常非常快的文件系统。所以不,我没有建议这样做。最好根据gc活动或其他条件定义一些触发器。
关于Stack-Traces:如果你遇到竞争条件,你的(多线程多??)应用程序冻结或减慢所有用户的阶段,我发现收集一些(3-5)线程很有帮助以固定间隔偏移3到5秒的转储(我们从5分钟开始,随着系统变得更加稳定,将其缩小到30米)然后将这些快照相互比较以识别可能的干扰。
虽然第一次迭代涉及jstack,但它后来演变为基于JMX的java应用程序访问并同时提取数据库锁定信息。
所以你的问题可以得到衷心的回答:"它取决于"。只有在看到OutOfMemoryError
时才应该提取内存转储。当可能存在高流量/冻结/线程拥塞时,线程转储可能很有用。
答案 2 :(得分:0)
你可以使用Javamelody,但你需要添加'它适用于您的应用程序。
https://github.com/javamelody/javamelody/
它允许您监视应用程序并查看历史记录,以及生成转储(但我不认为它可以在过去的两个事件之间为您提供转储)
答案 3 :(得分:0)
如果你想要完全内存转储,那么你必须去堆转储(jmap -F -dump:live,format = b,file =),这在生产系统中是不推荐的(Jan已经指出)。但是,还有其他方法可以在不影响生产系统性能的情况下定期关注内存使用情况:
jstat -gc Process_ID 300s
这将每五分钟捕获一次内存使用情况和垃圾回收详细信息。但是,它不会告诉您哪个对象消耗了多少内存等(由堆转储捕获)。但是,如果存在内存泄漏,您将能够随时查找。
jmap -histo Process_ID
这将生成应用程序的直方图信息。编写一个脚本并在每_分钟调用一次。
如果#1和#2显示内存泄漏的症状,那么只进行堆转储,但它可能会“挂起”您的应用程序,您可能必须在捕获堆转储后重新启动它。
就线程转储而言,如果要定期监视线程状态,可以使用以下命令。我熟悉他们每5分钟执行一次的应用程序并存储过去7天的数据。
jstack Process_ID
或(使用Java 8)
jcmd Process_ID Thread.print
在异常情况下,您总是可以每10秒捕获5/6个线程转储。
或者,如果您(或您的公司)负担得起,并且您希望定期关注系统,则可以查找New Relic种软件。