OOM的认识

目录

1 java.lang.StackOverflowError 栈空间撑爆

1.1 DEMO-栈溢出

1.2 StackOverflowError是异常还是错误(Error/Exception)

2 java.lang.OutOfMemoryError: Java heap space

2.1 DEMO-堆溢出

3 java.lang.OutOfMemoryError: GC ovverhead limit exceeded

 3.1 DEMO-GC

4 java.lang.OutOfMemoryError: Direct bufffer memory

4.1 DEMO-Direct bufffer memory

5 java.lang.OutOfMemoryError: unable to create new native thread 

5.1 DEMO-线程过多(在LINUX运行此程序代码,windows测试的时候要很久)

5.2 解决方案

6  java.lang.OutOfMemoryError:Metaspace

6.1 DEMO-Metaspace

7 参考文献


  • java.lang.StackOverflowError
  • java.lang.OutOfMemoryError: Java heap space
  • java.lang.OutOfMemoryError: GC ovverhead limit exceeded
  • java.lang.OutOfMemoryError: Direct bufffer memory
  • java.lang.OutOfMemoryError: unable to create new native thread 
  • java.lang.OutOfMemoryError:Metaspace

1 java.lang.StackOverflowError 栈空间撑爆

方法的加载在栈中,栈管运行,易出现在递归方法中,方法特别多把栈空间撑爆了。

1.1 DEMO-栈溢出

public class StackOverflowErrorDemo {
    //栈一般大小是512-1024
    public static void main(String[] args) {
        stackOverflowError();
    }
    private static void stackOverflowError() {
        stackOverflowError();
    }
}

 输出

1.2 StackOverflowError是异常还是错误(Error/Exception)

查看虚拟机错误

查看StackOverflowError,是错误级别

组织架构

2 java.lang.OutOfMemoryError: Java heap space

堆内存不够用了,对象太多了

2.1 DEMO-堆溢出

public class JavaHeapSpaceDemo {

    //前提,先把内存调小,-Xms10m -Xmx10m
    public static void main(String[] args) {
        String str = "test";
        while (true) {
            str+=str+new Random().nextInt(11111111)+new Random().nextInt(22222222);
            str.intern();
        }

        //或者定义一个超大数组
        //byte[] bytes = new byte[80*1024*1024];
    }
}

输出

3 java.lang.OutOfMemoryError: GC ovverhead limit exceeded

java内存极具上升,大量对象装载新建,GC超过最高警戒

 3.1 DEMO-GC

/**
 * User: mxy
 * Date: 2021/8/9
 * Time: 13:20
 * Description: GC过高
 * -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
 */
public class GCOverheadDemo {
    public static void main(String[] args) {
        int i = 0;
        List<String> list = new ArrayList<>();
        try {
            while (true) {
                list.add(String.valueOf(++i).intern());
            }
        } catch (Throwable e) {
            System.out.println("*********i" + i);
            e.printStackTrace();
            throw e;
        }
    }
}

输出


可以看出

每次GC的时候,前后数值对比没什么变化。GC效果不明显,所以GC overhead

4 java.lang.OutOfMemoryError: Direct bufffer memory

直接内存挂了,这个故障是非常严重的,netty(底层NIO),NIO程序会经常出现。

元空间并不在虚拟机中,而是使用本地内存。

System.out.println("配置的最大直接内存maxDirectMemory:" + (sun.misc.VM.maxDirectMemory()/(double)1024/1024)+"MB");

//输出
配置的maxDirectMemory:3609.0MB

4.1 DEMO-Direct bufffer memory

/**
 * User: mxy
 * Date: 2021/8/9
 * Time: 13:20
 * Description: GC过高
 * 容易出现在NIO程序
 * 未分配在JVM内存中,不属于GC管辖范围,在本地内存中经常建对象,本地内存用光,又不会GC,就会出现错误。
 * 本地内存:物理内存JVM外面默认能用的最大内存,未配置时默认1/4。
 *
 * -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
 */
public class DirectBufferMemoryDemo {
    public static void main(String[] args) {
        System.out.println("配置的最大直接内存maxDirectMemory:" + (sun.misc.VM.maxDirectMemory()/(double)1024/1024)+"MB");
        try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
        //配置 -XX:MaxDirectMemorySize=5m,使用6m
        ByteBuffer bb = ByteBuffer.allocateDirect(6*1024*1024);
    }
}

输出

5 java.lang.OutOfMemoryError: unable to create new native thread 

不能够创建更多的本地线程

程序部署到生产环境,创建线程的上线已经达到了,高并发经常会遇到。电商,物流,银行系统可能会遇到此故障。

题外话:

 Thread t1 = new Thread();
        t1.start();
        t1.start();
        //为什么再次start会报异常:
        // 因为底层代码中有threadStatus的控制,threadStatus = 0; 第二次进入threadStatus已改

5.1 DEMO-线程过多(在LINUX运行此程序代码,windows测试的时候要很久)

public class UnableCreateNewThreadDemo {
    public static void main(String[] args) {
        for (int i = 0;  ; i++) {
            System.out.println("****i="+i);
            new Thread(() -> {
                try {
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, ""+i).start();
        }
    }
}

输出

linux自身可能占用到了一部分,所以 i != 1024.

解决:杀掉进程

5.2 解决方案

5.2.1.非root用户登录linux系统测试

root用户有权限,可以一直new,一般人是非root用户

5.2.2.服务器级别调参调优

6  java.lang.OutOfMemoryError:Metaspace

元空间是方法区,装类的各种元素,常量池之类

初始大小约20M,不停的放类进去,就会满。

6.1 DEMO-Metaspace

输出

7 参考文献

以上内容均来自于下方视频,博客内容仅作为个人学习笔记记录

【1】Java面试_高频重点面试题 (第一、二、三季)_ 面试 第1、2、3季_柴林燕_周阳_哔哩哔哩_bilibili

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值