1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > JVM堆内存溢出排查

JVM堆内存溢出排查

时间:2023-11-15 14:57:05

相关推荐

JVM堆内存溢出排查

一:堆内存溢出模拟

我们先来做一个堆溢出的测试

1: 改小堆内存的设置

-Xms20m -Xmx20m -XX:-UseGCOverheadLimit

2:写一段死循环的代码

public class HeapOOMTest {public static void main(String[] args) {List<OOMObject> userList = new ArrayList<>();while (true){OOMObject oomObject = new OOMObject();oomObject.setBytes(new Byte[1]);userList.add(oomObject);}}}

@Datapublic class OOMObject {private Byte bytes[];}

运行之后,如意得到了异常:java.lang.OutOfMemoryError: Java heap space

Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat com.lixiucai.design.oom.HeapOOMTest.main(HeapOOMTest.java:17)

细心的小伙伴可能要问了,上面设置的-XX:-UseGCOverheadLimit 参数是干嘛的?这个是禁用GC overhead limt exceed检查,因为我们堆内存设置的特别小,运行的时候,总是会抛出java.lang.OutOfMemoryError: GC overhead limit exceeded,而不是我们期望的java.lang.OutOfMemoryError: Java heap space,所以我们把它禁用掉。

GC overhead limt exceed检查是Hotspot VM 1.6定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。Sun 官方对此的定义是:“并行/并发回收器在GC回收时间过长时会抛出OutOfMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作。“

上面的程序很简单,我们通过代码检查,就会发现是死循环导致的,OOMObject这个对象始终无法被GC释放掉,然后从年轻代的区域,存活到老年代的区域,一直累加,突破了堆内存设定上限,然后OOM。但当代码很多的时候,我们不可能通过这种一行一行检查代码的方式来排查问题,若是有一种工具能还原OOM时,JVM的内存情况就好了,JVN提供了一个参数,使得在OOM的时候可以转储堆内存快照dump文件,然后我们可以使用JDK自带的工具Visual VM来查看分析dump文件。

二:堆内存dump文件生成与分析

1.JVM设置在OOM时生成dump文件

在JVM的参数里设置如下

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\dump

第一个参数表示在OOM的时候生成dump文件,第二个参数设置生成的dump文件的路径

2.使用Visual VM来分析dump文件

Visual VM,自从 JDK 6 Update 7 以后已经作为 Oracle JDK 的一部分,位于 JDK 根目录的 bin 文件夹下,无需安装,直接运行即可。我们将服务器上生成的dump文件下载到本地,然后使用本地的Visual VM载入它。

点击 文件 --> 装入,然后选择文件类型为 堆Dump,点击打开

点击堆转储上的线程,可以查看线程日志,然后我们点击 类 页签,显示界面如下

列表是支 持排序的,我们按实例数或者大小做下倒序,就会发现堆内存里比较大的对象OOMObject排在最前面,然后就是我们要在代码里去找这些大对象出现的地方,排查代码的问题。

三:堆内存溢出的解决方案

1.代码的问题:

排查这些大对象出现的地方,是否有死循环,是否有没有做分页,做全表查询的代码等等。

2.堆内存确实设置的过小,改大它:

-Xms1024m -Xmx1024m

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。