当 Java 中存在堆溢出时,我如何知道啥在使用内存?

Posted

技术标签:

【中文标题】当 Java 中存在堆溢出时,我如何知道啥在使用内存?【英文标题】:How can I tell what is using the memory when there is a heap overflow in Java?当 Java 中存在堆溢出时,我如何知道什么在使用内存? 【发布时间】:2010-12-31 22:12:11 【问题描述】:

我对分析略知一二,但我特别感兴趣的是,当我遇到这些堆溢出异常时,拥有所有内存的是什么。

我将在大约一个小时的调试后开始获取它们。我希望有某种转储或其他东西,我可以使用它来获取程序启动时周围的实例列表。

顺便说一句,对不起,如果这是一个懒惰的问题。我真的应该花一些时间来学习分析。

格雷

【问题讨论】:

【参考方案1】:

您可以使用jmap -dump 来生成堆转储。并且您可以使用各种程序分析堆转储,例如 jhat 或 VisualVM(两者都随 JDK 一起提供)。

现在,您可以通过 Google 搜索更多内容。 :-)

【讨论】:

@stacker:感谢您的 +1!我们实际上在工作中经常使用 jhat,我实际上开始在工作时间改进它:github.com/on-site/fasthat(我还没有实现任何令人兴奋的东西,但我有一个我们团队真正想开始的功能路线图使用。)【参考方案2】:

请注意,OutOfMemoryError 的类型很重要。它有很多变体。阅读异常附带的消息。它可能是“Java heap space”,表示与堆相关的错误,但也可能有另一条消息,指的是其他内存区域(例如参见this post)。

假设存在堆分配问题,您可以使用 JVM 标志 XX:+HeapDumpOnOutOfMemoryError 以便在发生错误时获得完整的堆转储。然后,您可以使用一些堆转储读取器并分析结果(例如VisualVM 或jhat)。

正如其他回复所提到的,您也可以使用命令行工具 jmap。我将从 jmap -histo 开始,它创建不同类的简单直方图。如果您看到一个类的实例数量不合理,那么您就有内存泄漏嫌疑。

【讨论】:

crash发生后可以使用jmap吗? @Grae:如果 java 进程关闭,你就不能。但是您可以在 jmap (-histo) 崩溃之前运行几次,然后了解哪种对象占用了您的堆内存。 但是,你的解决方案,使用 XX:+HeapDumpOnOutOfMemoryError 会在崩溃后工作吗? @Grae:是的,它应该在抛出 OutOfMemoryError 的那一刻创建一个完整的堆转储。【参考方案3】:

安装JRockit VM,然后使用JRockit 命令中心:) 非常非常好,并且提供了方法名称列表和这些方法消耗的CPU 时间,以及系统中浮动的对象。

【讨论】:

【参考方案4】:

Sun Java 6 JDK 中最有用的工具之一是“jvisualvm”,它可以附加到以前启动的进程并执行您需要执行的内存分析来解决此问题。

(您也可以手动下载 VisualVM,但 JDK 可能是最简单的启动和运行方式)。

有关初始使用说明,请参阅 http://download.oracle.com/javase/6/docs/technotes/guides/visualvm/applications_local.html

【讨论】:

这很有用:在 OOME 上启用堆转储。如果您希望 Java VisualVM 在应用程序遇到 OutOfMemoryException 时自动进行堆转储,请选择此选项。【参考方案5】:

VisualVM 是免费且有用的。 JProfiler 和 YourKit 不是免费的,而且更有用。

【讨论】:

以上是关于当 Java 中存在堆溢出时,我如何知道啥在使用内存?的主要内容,如果未能解决你的问题,请参考以下文章

实战JAVA虚拟机 JVM故障诊断与性能优化

在堆溢出时保存快照

JAVA内存泄露查询

Java虚拟机八 分析Java堆

java堆溢出

Java内存溢出问题总结