Java 内存模型 - 内存溢出 实战

1、Java 堆内存溢出

  Java 堆内存主要用于存放对象实例,只要不断的创建对象,并且摆正GC Roots 到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象创建数量达到堆内存容量限制之后就会产生堆内存OutOfMemoryError 溢出异常。

  示例代码:

//VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
public
class test { static class OOMObject{} public static void main(String[] args) { List<OOMObject> list = new ArrayList<>(); while (true) list.add(new OOMObject()); } }

  异常信息:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid12488.hprof ...
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3210)
    at java.util.Arrays.copyOf(Arrays.java:3181)
    at java.util.ArrayList.grow(ArrayList.java:261)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
    at java.util.ArrayList.add(ArrayList.java:458)
    at com.oops.boot.test.main(test.java:15)
Heap dump file created [28410427 bytes in 0.234 secs]

Process finished with exit code 1

  总结:当对象创建数量达到堆内存容量限制之后就会产生堆内存OutOfMemoryError 溢出异常。例如:无限制创建对象。

2、虚拟机栈 和 本地栈溢出

  • 如果线程请求的栈深度大于虚拟机所允许的深度则抛出StackOverflowError异常。
  • 如果虚拟机在扩展时无法申请到足够内存空间则抛出OutOfMemoryError 异常。

  2.1 StackOverflowError异常

  示例代码:

public class JavaVNStackSOF {

    private int stacklLength = 1;

    public void stackLeak(){

        stacklLength++;
        stackLeak();
    }

    public static void main(String[] args) throws Throwable{

        JavaVNStackSOF oom = new JavaVNStackSOF();

        try {
            oom.stackLeak();
        } catch (Exception e) {
            System.out.println("stack length: " + oom.stacklLength);
            throw e;
        }
    }
}

  异常代码:

Exception in thread "main" java.lang.StackOverflowError
    at com.oops.boot.JavaVNStackSOF.stackLeak(JavaVNStackSOF.java:10)
    at com.oops.boot.JavaVNStackSOF.stackLeak(JavaVNStackSOF.java:11)
    at com.oops.boot.JavaVNStackSOF.stackLeak(JavaVNStackSOF.java:11)
    at com.oops.boot.JavaVNStackSOF.stackLeak(JavaVNStackSOF.java:11)

后续省略......

  总结:在单个线程下,无论是由于帧太大还是虚拟机容量太小,当内存无法分配的时候,虚拟机都会抛出 StackOverflowError异常

3、方法区 和运行时常量池溢出

  示例代码:

//VM Args : -XX:PermSize=10m -XX:MaxPermSize=10m
public class RunTimeConstantPoolOOM {

    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        int i = 0;
        while (true) {
            list.add(String.valueOf(i++).intern());
        }
    }
}

 

posted @ 2019-07-11 16:17  Axuduo  阅读(155)  评论(0编辑  收藏  举报