首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何调试Java OutOfMemory异常?

如何调试Java OutOfMemory异常?
EN

Stack Overflow用户
提问于 2010-12-22 18:01:04
回答 8查看 21.3K关注 0票数 19

调试java.lang.OutOfMemoryError异常的最佳方法是什么?

当这发生在我们的应用程序中时,我们的应用服务器(Weblogic)会生成一个堆转储文件。我们应该使用堆转储文件吗?我们应该生成一个Java线程转储吗?到底有什么区别?

更新:生成线程转储的最佳方法是什么?kill -3 (我们的应用程序运行在Solaris上)是杀死应用程序并生成线程转储的最佳方法吗?有没有一种方法可以生成线程转储,而不是杀死应用程序?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 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 )。

步骤4.使用IBM的堆分析仪内存分析器打开转储文件

将为您提供一个树,其中包含在错误发生时还活着的所有对象。当问题打开时,它很可能会直接指向。

注意:给HeapAnalyzer足够的内存,因为它需要加载整个转储!

代码语言:javascript
复制
java -Xmx10g -jar ha456.jar

步骤5.确定最大使用堆的区域

浏览对象树,找出不必要地保存在周围的对象。

注意,所有对象都是必需的,这意味着您需要一个更大的堆。Size和调音适当地

步骤6.修复您的代码

确保只保留实际需要的对象。及时从集合中删除项。确保不再保留对不再需要的对象的引用,只有这样,它们才能被垃圾收集。

票数 12
EN

Stack Overflow用户

发布于 2010-12-22 18:55:46

我成功地使用了日食内存分析器(MAT)Java Visual VM的组合来分析堆转储。MAT有一些您可以运行的报告,可以让您大致了解在代码中集中精力的地方。VisualVM有一个更好的接口(在我看来),用于实际检查您感兴趣的各种对象的内容。它有一个过滤器,您可以让它显示特定类的所有实例,并查看它们被引用的位置以及它们自己引用的内容。我已经有一段时间没有使用这两种工具了,它们现在可能有一个更接近的特性集。当时,这两种方法对我都很管用。

票数 7
EN

Stack Overflow用户

发布于 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进程。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4512147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档