欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java虚拟机:实战OutOfMemoryError异常

程序员文章站 2022-03-24 09:15:49
...

  在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其它几个运行时数据区域都有发生OutOfMemoryError(OOM)

一、Java堆溢出

/**
 * @author: hs
 * @Date: 2019/12/11 10:25
 * @Description:
 * -Xms30m -Xmx30m -XX:+PrintGCDetails -XX:SurvivorRatio=8
 * -XX:+HeapDumpOnOutOfMemoryError
 */
public class HeapOOM {
    static class OOMObject{

    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        while (true){
            list.add(new OOMObject());
        }
    }
}

将堆的最小值参数-Xms和最大值参数-Xmx设置为一样即可避免堆自动扩展,通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析。
如图:
Java虚拟机:实战OutOfMemoryError异常
从当前堆快照分析如图:
Java虚拟机:实战OutOfMemoryError异常
Java虚拟机:实战OutOfMemoryError异常
线程0xfed12730中list存放大量对象,重点是确认内存中的对象是否是必要的,也就是要先分清到底是内存泄漏还是内存溢出。

二、Java虚拟机栈和本地方法栈溢出

/**
 * @author: hs
 * @Date: 2019/12/11 14:56
 * @Description:
 * VM args: -Xss128k
 */
public class JVMStackSOF {

    private int stackLength = 1;

    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) {
        JVMStackSOF stackSOF = new JVMStackSOF();
        try {
            stackSOF.stackLeak();
        } catch (Exception e) {
            System.out.println("length:"+stackSOF.stackLength);
            throw e;
        }
    }
}

结果如图:
Java虚拟机:实战OutOfMemoryError异常
  由于在Hotspot虚拟机中并不区分虚拟机栈和本地方法栈,因此对于HotSpot来说,-Xoss参数虽然存在,但实际是无效的。栈容量只有-Xss来设定。
  关于虚拟机栈和本地方法栈在JVM规范中描述了两种异常:1.如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出*Error。2.如果虚拟机在扩展栈时无法申请足够的内存空间,则抛出OutOfMemoryError异常。