Java:在不使用 jmap 或不挂起应用程序的情况下获取堆转储
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20832793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java : Get heap dump without jmap or without hanging the application
提问by Arun
In few circumstance, our application is using around 12 GB of memory. We tried to get the heap dump using jmap utility. Since the application is using some GB of memory it causes the application to stop responding and causes problem in production.
在少数情况下,我们的应用程序使用大约 12 GB 的内存。我们尝试使用 jmap 实用程序获取堆转储。由于应用程序正在使用一些 GB 的内存,它会导致应用程序停止响应并导致生产问题。
In our case the heap usage suddenly increases from 2-3 GB to 12GB in 6 hours. In an attempt to find teh memory usage trend we tried to collect the heap dump every one hour after restarting the application. But as said since using the jmap causes the application to hang we need to restart it and we are not able to get the trend of memory usage.
在我们的例子中,堆使用量在 6 小时内从 2-3 GB 突然增加到 12 GB。为了找出内存使用趋势,我们尝试在重新启动应用程序后每隔一小时收集一次堆转储。但如前所述,由于使用 jmap 导致应用程序挂起,我们需要重新启动它,我们无法获得内存使用趋势。
Is there a way to get the heap dump without hanging the application or is there a utility other than jmap to collect heap dump.
有没有办法在不挂起应用程序的情况下获取堆转储,或者是否有除 jmap 之外的实用程序来收集堆转储。
Thoughts on this highly appreciated, since without getting the trend of memory usage it is highly difficult to fix the issue.
对此高度赞赏的想法,因为如果不了解内存使用趋势,就很难解决问题。
Note: Our application runs in CentOS.
注意:我们的应用程序在 CentOS 中运行。
Thanks, Arun
谢谢,阿伦
回答by Stephen C
First of all, it is (AFAIK) essential to freeze the JVM while a thread dump / snapshot is being taken. If JVM was able to continue running while the snapshot was created, it would be next to impossible to get a coherent snapshot.
首先,在拍摄线程转储/快照时冻结 JVM 是(AFAIK)必不可少的。如果 JVM 能够在创建快照时继续运行,则几乎不可能获得一致的快照。
So are there other ways to get a heap dump?
那么还有其他方法可以获得堆转储吗?
You can get a heap dump using VisualVM as described here.
You can get a heap dump using jconsole or Eclipse Memory Analyser as described here.
But all of these are bound to cause the JVM to (at least) pause.
但所有这些都必然会导致 JVM(至少)暂停。
If your application is actually hanging (permanently!) that sounds like a problem with your application itself. My suggestion would be to see if you can track down thatproblem before looking for the storage leak.
如果您的应用程序实际上挂起(永久!),这听起来像是您的应用程序本身的问题。我的建议是在查找存储泄漏之前查看您是否可以追踪该问题。
My other suggestion is that you look at a single heap dump, and use the stats to figure out what kind(s) of object are using all of the space ... and why they are reachable. There is a good chance that you don't need the "trend" information at all.
我的另一个建议是,您查看单个堆转储,并使用统计信息找出正在使用所有空间的对象类型……以及它们为何可访问。您很有可能根本不需要“趋势”信息。
回答by Lolo
To add to Stephen's answers, you can also trigger a heap dump via API for the most common JVM implementations:
要添加斯蒂芬的答案,您还可以通过 API 为最常见的 JVM 实现触发堆转储:
回答by FooMan
You can use GDB to get the heap dump without running jmap on the target VM however this will still hang the application for the amount of time required to write the heap dump to disk. Assuming a disk speed of 100MB/s (a basic mirrored array or single disk) this is still 2 minutes of downtime. http://blogs.atlassian.com/2013/03/so-you-want-your-jvms-heap/
您可以使用 GDB 来获取堆转储,而无需在目标 VM 上运行 jmap,但这仍然会在将堆转储写入磁盘所需的时间内挂起应用程序。假设磁盘速度为 100MB/s(基本镜像阵列或单个磁盘),这仍然是 2 分钟的停机时间。 http://blogs.atlassian.com/2013/03/so-you-want-your-jvms-heap/
The only true way to avoid stopping the JVM is transactional memory and a kernel that takes advantage of it to provide a process snapshot facility. This is one of the dreams of the proponents of STM but it's not available yet. VMWare's hot-migration comes close but depends on your allocation rate not exceeding network bandwidth and it doesn't save snapshots. Petition them to add it for you, it'd be a neat feature.
避免停止 JVM 的唯一真正方法是事务内存和利用它来提供进程快照功能的内核。这是STM支持者的梦想之一,但目前还没有。VMWare 的热迁移很接近,但取决于您的分配率不超过网络带宽,并且不保存快照。请他们为您添加它,这将是一个很好的功能。
回答by Tim Long
Try the following. It comes with JDK >= 7:
请尝试以下操作。它带有 JDK >= 7:
/usr/lib/jvm/jdk-YOUR-VERSION/bin/jcmd PID GC.heap_dump FILE-PATH-TO-SAVE
Example:
例子:
/usr/lib/jvm/jdk1.8.0_91/bin/jcmd 25092 GC.heap_dump /opt/hd/3-19.11-jcmd.hprof
This dumping process is much faster than dumping with jmap! Dumpfiles are much smaller, but it's enough to give your the idea, where the leaks are.
这个转储过程比用 jmap 转储快得多!转储文件要小得多,但足以让您了解泄漏的位置。
At the time of writing this answer, there are bugs with Memory Analyzer and IBM HeapAnalyzer, that they cannot read dumpfiles from jmap (jdk8, big files). You can use Yourkit to read those files.
在撰写此答案时,内存分析器和 IBM HeapAnalyzer 存在错误,即它们无法从 jmap(jdk8,大文件)读取转储文件。您可以使用 Yourkit 来读取这些文件。
回答by Nathan
A heap dump analyzed with the right tool will tell you exactly what is consuming the heap. It is the best tool for tracking down memory leaks. However, collecting a heap dump is slow let alone analyzing it.
使用正确的工具分析的堆转储将告诉您究竟是什么在消耗堆。它是跟踪内存泄漏的最佳工具。但是,收集堆转储很慢,更不用说分析它了。
With knowledge of the workings of your application, sometimes a histogram is enough to give you a clue of where to look for the problem. For example, if MyClass$Inner
is at the top of the histogram and MyClass$Inner
is only used in MyClass
, then you know exactly which file to look for a problem.
了解应用程序的工作原理后,有时直方图足以为您提供寻找问题的线索。例如,如果MyClass$Inner
位于直方图的顶部并且MyClass$Inner
仅在 中使用MyClass
,则您确切地知道要查找哪个文件的问题。
Here's the command for collecting a histogram.
这是用于收集直方图的命令。
jcmd
pidGC.class_histogram filename=histogram.txt
jcmd
进程号GC.class_histogram filename=histogram.txt