java堆内存溢出展示以及优化思路

java堆内存溢出展示以及优化思路

一、JAVA堆溢出
本文只针对java堆内存溢出,不针对其它内存溢出:
之前的的一篇文章《java虚拟机的学习笔记》已经讲过,Java堆是用来存储对象实例的。所以想要演示出OOM效果,我们就无限制不停的创建新的对象实例,且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,当实例的数量触及到了堆的最大容量值的时候,就会产生内存溢出异常(OutOfMemoryError);

二、模拟堆内存溢出测试

由于现在大家的电脑配置都很高,为了尽快看到java堆内存溢出的异常,我们可以重新设置一下-Xmx和-Xms的值为20M;下文通过jconsole展示内存升高效果,就没有设置这两个值;

测试代码

package com.demo.spring.test.jvm;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description: java堆内存溢出测试
 * @Author: yangshilei
 * 为了方便测试:需要将idea或者eclipse的-Xms和-Xmx参数均设置为20M;
 * 1.-Xms:堆的最小值
 * 2.-Xmx:堆的最大值
 * 3.-Xms的值等于-Xmx表示避免堆内存自动扩展
 */
public class HeapOutOfMemory {
    
    

    static class OOMObject{
    
    
        public OOMObject(){
    
    
            System.out.println("hello world");
        }
    }

    public static void main(String[] args) {
    
    

        List<OOMObject> list = new ArrayList<>();

        // 在无限循环中不停的创建对象实例
        while (true){
    
    
            list.add(new OOMObject());
        }
    }
}

我们可以使用jconsole来看一下程序执行时候的内存变化情况:堆内存也有回收,但是每次都回收不干净,逐渐增加,导致堆内存升高。
在这里插入图片描述
我们还可以在VM概要中看到当前内存和最大内存的使用情况:
在这里插入图片描述
当达到内存溢出的时候:jconsole显示连接异常错误结果,如下文:
在这里插入图片描述

十一月 24, 2020 10:29:28 上午 ClientCommunicatorAdmin Checker-run
警告: Failed to check connection: java.net.SocketException: Connection reset
十一月 24, 2020 10:29:28 上午 ClientCommunicatorAdmin Checker-run
警告: stopping

此时代码程序返回的异常结果:
在这里插入图片描述

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2245)
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.grow(ArrayList.java:213)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:187)
    at java.util.ArrayList.add(ArrayList.java:411)
    at com.demo.test.HeapOOM.main(HeapOOM.java:12)

当看到OutOfMemoryError的时候,我们还不知道是什么内存溢出,跟随进一步的提示"Java heap space",可以判定为java堆内存溢出!

三、堆内存溢出的优化方式
1、检查程序代码
首先就是要检查程序是否有无限循环创建实例的代码,这个不解决,再多的内存也不够用;其次,从代码上检查是否存在某些对象的生命周期过长、持有状态时间过长、存储结构设计不合理等等,尽量减少程序运行时期对内存的消耗。

2.增加Java虚拟机-Xms和-Xmx值
如果机器的内存还有多余的空间,我们将这两个值适当的调高一下;
一般来说:为了避免java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源,通常将这两个值大小设置一样。
-Xms:表示java虚拟机堆区内存初始内存分配的大小,通常为操作系统可用内存的1/64大小即可
-Xmx:表示java虚拟机堆区内存可被分配的最大上限,通常为操作系统可用内存的1/4大小。

猜你喜欢

转载自blog.csdn.net/qq_37488998/article/details/109902796