如何制作Java应用程序的"内存转储"?

15

我有一个Java应用程序,不幸的是,它在一段时间后开始消耗相当大的内存。更加复杂的是,它不仅仅是一个Java应用程序,还是一个JavaFX 2应用程序。

我怀疑存在某些内存泄漏,甚至可能是在底层JavaFX调用和本地库中。

理想的解决方案是在某个时刻获取所有Java对象的转储(包括它们的内存使用情况),然后分析该转储。是否有某种方式可以实现这一点?


你在哪个平台上工作?Linux、Win、Mac? - Balázs Németh
@BalázsMáriaNémeth - Linux(Ubuntu 10.10)。 - Rogach
4个回答

18
使用`jmap -heap:format=b `命令创建堆的二进制转储文件,然后可以将其加载到多个工具中,我最喜欢的是"Eclipse Memory Analyzer"。

6

有许多方法可以获取堆转储,从简单的工具如jmap到更高级的工具如JVisualVM或甚至商业工具如JProfiler。然而,正确解释这些转储可能会很棘手,因此您可能希望发布您要查找的内容。您是在寻找内存泄漏,还是对您的应用程序有一个总体感觉?


我正在寻找一些内存泄漏,甚至可能在本地库中 :( - Rogach
如果JavaFX类确实是造成泄漏的原因,那么找到泄漏将会相当棘手(尽管我不知道是否存在任何问题)。如果您可以访问它,我建议使用JProfiler进行此操作,尽管我确信其他应用程序(我可能不知道的)也可以完成此工作。基本方法是获取堆转储,检查可疑的对象集合,并使用工具将实例跟踪回其GC根源(这是您不想手动执行的操作)。此功能基本上将告诉您为什么未对实例进行垃圾回收。 - sarcan
我现在正在使用jvisalvm,根据我的应用程序堆大小缓慢增长的事实来判断,这不是本地泄漏的结果,而是Java对象的泄漏。因此,我希望这将很容易解决。感谢您的帮助! - Rogach
请牢记,一个不断增长的堆并不意味着存在内存泄漏,直到你实际上收到OOMException异常。根据您的垃圾回收器,可能只是未被回收的垃圾,在进行完整收集之前一直留在那里。 - sarcan
很不幸,我通过jvisualvm强制进行垃圾收集的方式进行了检查,但似乎并没有未回收的垃圾。实际问题是,即使应用程序完全闲置,内存却不断累积。 - Rogach
如果它正在累积垃圾,那么它将会执行某些操作。你是否检查过(通过JVisualVM)CPU时间的消耗在哪里? - sarcan

5

你可以使用jvisualvm工具,它有插件可以查看实时内存并将其导出。


3

在研究抓取“此刻JVM状态”的方法时,我重新发现了这篇文章(archive.org archive)。在使用jmap提取的堆大小只有MBeans报告大小的一半时,我会将其添加以完整性为考虑:

su $JVM_OWNER -c "gcore -o /tmp/jvm.core $YOUR_JVM_PID"
su $JVM_OWNER -c "jmap -dump:format=b,file=jvm.hprof /usr/bin/java /tmp/jvm.core"

需要安装gdb(用于 gcore)和JDK(用于jmap)。还请注意,您可能需要调整 /usr/bin/java 的路径以匹配进程使用的JVM。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接