调试java.lang.OutOfMemoryError异常的最佳方法是什么?
当这发生在我们的应用程序中时,我们的应用服务器(Weblogic)会生成一个堆转储文件。我们应该使用堆转储文件吗?我们应该生成一个Java线程转储吗?到底有什么区别?
更新:生成线程转储的最佳方法是什么?kill -3 (我们的应用程序运行在Solaris上)是杀死应用程序并生成线程转储的最佳方法吗?有没有一种方法可以生成线程转储,而不是杀死应用程序?
发布于 2019-01-11 09:49:08
在Java中分析和修复内存不足的错误非常简单.
在Java中,占用内存的对象都链接到其他对象,形成了一棵巨大的树。这样做的目的是找到树中最大的分支,这通常会指向内存泄漏的情况(在Java中,您泄漏内存不是当您忘记删除一个对象时,而是当您忘记忘记对象时,即在某个地方保存了对它的引用)。
步骤1.在运行时启用堆转储
使用-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp运行您的进程
(始终启用这些选项是安全的。根据需要调整路径,它必须由java用户写)
步骤2.复制错误
让应用程序运行,直到出现OutOfMemoryError。
JVM将自动编写类似于java_pid12345.hprof的文件。
步骤3.获取转储
将java_pid12345.hprof复制到您的PC上(它至少会和您的最大堆大小一样大,因此如果需要的话可以得到相当大的gzip )。
将为您提供一个树,其中包含在错误发生时还活着的所有对象。当问题打开时,它很可能会直接指向。

注意:给HeapAnalyzer足够的内存,因为它需要加载整个转储!
java -Xmx10g -jar ha456.jar步骤5.确定最大使用堆的区域
浏览对象树,找出不必要地保存在周围的对象。
注意,所有对象都是必需的,这意味着您需要一个更大的堆。Size和调音堆适当地。
步骤6.修复您的代码
确保只保留实际需要的对象。及时从集合中删除项。确保不再保留对不再需要的对象的引用,只有这样,它们才能被垃圾收集。
发布于 2010-12-22 18:55:46
我成功地使用了日食内存分析器(MAT)和Java Visual VM的组合来分析堆转储。MAT有一些您可以运行的报告,可以让您大致了解在代码中集中精力的地方。VisualVM有一个更好的接口(在我看来),用于实际检查您感兴趣的各种对象的内容。它有一个过滤器,您可以让它显示特定类的所有实例,并查看它们被引用的位置以及它们自己引用的内容。我已经有一段时间没有使用这两种工具了,它们现在可能有一个更接近的特性集。当时,这两种方法对我都很管用。
发布于 2016-05-19 15:32:20
调试
java.lang.OutOfMemoryError异常的最佳方法是什么?
OutOfMemoryError描述消息描述中的错误类型。您必须检查错误消息的描述以处理异常。
内存不足异常有多种根本原因。有关详细信息,请参阅甲骨文文档页面。
java.lang.OutOfMemoryError: Java heap space
原因:详细消息Java堆空间表示无法在Java堆中分配对象。
java.lang.OutOfMemoryError: GC Overhead limit exceeded
原因:详细消息"GC开销超过极限“表示垃圾收集器一直在运行,而Java程序进展非常缓慢
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
原因:详细消息“请求的数组大小超过VM限制”表示应用程序(或该应用程序使用的API)试图分配大于堆大小的数组。
java.lang.OutOfMemoryError: Metaspace
原因: Java类元数据( Java类的虚拟机内部表示)被分配到本机内存中(这里称为metaspace)。
java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?
原因:详细信息“合理地请求大小字节。交换空间之外?”似乎是OutOfMemoryError异常。但是,当来自本机堆的分配失败并且本机堆可能接近耗尽时,Java HotSpot VM代码会报告这个明显的异常。
java.lang.OutOfMemoryError: Compressed class space
原因:在64位平台上,指向类元数据的指针可以用32位偏移量(使用UseCompressedOops)表示。这是由命令行标志UseCompressedClassPointers (默认情况下)控制的。
如果使用UseCompressedClassPointers,则类元数据可用的空间大小固定在CompressedClassSpaceSize数量。如果UseCompressedClassPointers所需的空间超过CompressedClassSpaceSize,则抛出具有详细压缩类空间的java.lang.OutOfMemoryError。
注意:有不止一种类元数据- klass元数据和其他元数据。只有klass元数据存储在以CompressedClassSpaceSize为界的空间中。其他元数据存储在Metaspace中。
我们应该使用堆转储文件吗?我们应该生成一个Java线程转储吗?到底有什么区别?
是。您可以使用这个堆堆转储文件来调试这个问题,使用视景或垫子之类的分析工具,您可以使用线程转储来进一步了解线程的状态。
请参考这个SE问题来了解不同之处:
Websphere中javacore、线程转储和堆转储的区别
生成线程转储的最佳方法是什么?杀害-3 (我们的应用程序运行在Solaris上)是杀死应用程序并生成线程转储的最佳方法吗?有没有一种方法可以生成线程转储,而不是杀死应用程序?
kill -3 <process_id>生成线程转储,此命令不会终止java进程。
https://stackoverflow.com/questions/4512147
复制相似问题