当这种情况发生在我们的应用程序中时,我们的应用服务器(Weblogic)会生成一个堆转储文件。我们应该使用堆转储文件吗?我们应该生成Java线程转储吗?这两者到底有什么区别?
更新:生成线程转储的最佳方法是什么?在Solaris上,使用kill -3(我们的应用程序运行在Solaris上)杀死应用程序并生成线程转储是最好的方法吗?是否有一种方法可以生成线程转储但不杀死应用程序?
-XX:+ HeapDumpOnOutOfMemoryError -XX:HeapDumpPath = / tmp
运行进程。 OutOfMemoryError
。 java_pid12345.hprof
的文件。 java_pid12345.hprof
复制到计算机上(它至少与最大堆大小一样大,因此可能会很大-如果需要,请对其进行gzip)。堆分析器将向您展示所有在错误发生时存活的对象的树形结构。很可能它会在打开时直接指出问题所在。
注意:给HeapAnalyzer足够的内存,因为它需要加载整个转储文件!java -Xmx10g -jar ha456.jar
浏览对象树,识别不必要的对象。
请注意,也可能发生所有对象都是必需的情况,这意味着您需要更大的堆。适当地调整堆的大小和配置。
确保只保留您实际需要的对象。及时从集合中删除项目。确保不保留对不再需要的对象的引用,只有这样它们才能被垃圾回收。
调试 java.lang.OutOfMemoryError
异常的最佳方法是什么?
OutOfMemoryError
描述了错误的类型。您需要检查错误消息的描述以处理异常。
内存不足异常有各种根本原因。请参考 Oracle 文档页面 获取更多详细信息。
java.lang.OutOfMemoryError: Java heap space
:
原因:Java 堆空间的详细消息表示无法在 Java 堆中分配对象。
java.lang.OutOfMemoryError: GC Overhead limit exceeded
:
原因:"GC overhead limit exceeded" 详细消息表示垃圾回收器一直运行,而 Java 程序进展非常缓慢。
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
:
UseCompressedClassPointers
,类元数据可用空间的大小将固定为CompressedClassSpaceSize
。如果UseCompressedClassPointers
所需的空间超过了CompressedClassSpaceSize
,将抛出一个带有详细信息"Compressed class space"的java.lang.OutOfMemoryError
。
我们应该使用堆转储文件吗?我们应该生成Java线程转储吗?两者之间到底有什么区别?
是的。您可以使用这个堆转储文件来使用像visualvm或mat这样的性能分析工具来调试问题。您可以使用线程转储来进一步了解线程的状态。
生成线程转储的最佳方法是什么?在Solaris上运行的应用程序中,kill -3是杀死应用程序并生成线程转储的最佳方法吗?有没有一种方法可以生成线程转储而不杀死应用程序?
kill -3 <process_id>
会生成线程转储,而且这个命令不会杀死Java进程。jmap -histo:live <pid> | head -n <top N things to look for> > <output.log>
OutOfMemoryError
问题非常困难。我建议使用性能分析工具。JProfiler效果不错,我以前用过,它非常有帮助,但我相信还有其他同样好的工具。new
创建的所有对象。如果内存不足,则这将非常大。它显示了每种类型的对象数量。看起来IBM提供了一个分析堆转储的工具:http://www.alphaworks.ibm.com/tech/heaproots;更多信息请参见http://www-01.ibm.com/support/docview.wss?uid=swg21190476。
一旦您获得了查看堆转储的工具,请查看线程堆栈中处于运行状态的任何线程。它可能是那些出现错误的线程之一。有时,堆转储将告诉您哪个线程在顶部出现了错误。
这应该指向正确的方向。然后使用标准调试技术(日志记录、调试器等)来锁定问题。使用Runtime类获取当前内存使用情况,并在涉及的方法或进程执行时记录它。
.hprof
文件,还是其他什么文件? - skaffman