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);
        }
    }

}
@Data
public class OOMObject {
    private Byte bytes[];
}

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

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李秀才

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值