Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)

Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)

书上P39

1. 堆内存溢出

不断地创建对象, 而且保证创建的这些对象不会被回收即可(让GC Root可达).

/**
 * 堆内存溢出demo
 * VM Options: -Xms6m -Xmx6m
 */
public class HeapOOM {
    static class OOMObejct {

    }

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

 会内存溢出, 输出结果如下:

如果是用下面这段代码的话, 是不会内存溢出的. 因为有GC. 每次new 的 Object在下次for循环中都退出了作用域, 虚拟机栈不再持有对象的引用. 所以会被GC掉. 不会溢出.

/**
 * 堆内存溢出demo
 * VM Options: -Xms6m -Xmx6m
 */
public class HeapOOM {
    static class OOMObejct {

    }

    public static void main(String[] args) {
        while (true) {
            new OOMObejct();
        }
    }
}

 visualVM的堆内存图如下:

2. 虚拟机栈溢出

/**
 * 栈内存溢出demo
 * VM Options: -Xms6m -Xmx6m
 */
public class StackOverflow {
    private int stackDepth;

    private void stackLeak() {
        stackDepth++;
        stackLeak();
    }

    public static void main(String[] args) {
        StackOverflow oom = new StackOverflow();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println(oom.stackDepth);
            System.err.println(e.toString());
        }
    }
}

 输出结果如下(下面部分结果可能根据机器环境不同而不同):  

3. 创建线程导致的内存溢出

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 创建线程导致的内存溢出demo
 * VM Options: -Xms6m -Xmx6m
 */
public class CreateThreadOOM {
    static AtomicInteger counter = new AtomicInteger(0);

    public static void main(String[] args) {
        while (true) {
            new Thread(() -> {
                try {
                    System.out.println(counter.incrementAndGet());
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

 输出结果如下(下面部分结果可能根据机器环境不同而不同): 

4. 直接内存溢出

这段代码我这里没有运行出书上的效果...

书上的意思应该是, 设定了直接内存大小最大为10M后, 继续申请的话, 就会报异常..

在我电脑上, 虽然也设置了MaxDirectMemorySize=10m , 但是这玩意硬生生地申请了10G的虚拟内存也没停下, 最后被操作系统强制停止了.....(运行了几次电脑都快没电了)

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * VM Options: -Xms6m -Xmx6m -XX:MaxDirectMemorySize=10m
 */
public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1014;

    public static void main(String[] args) throws IllegalAccessException, InterruptedException {
        Field unsafeFile = Unsafe.class.getDeclaredFields()[0];
        unsafeFile.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeFile.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);
            Thread.sleep(10);
        }
    }
}

  

posted @ 2018-08-10 12:15  GoldArowana  阅读(488)  评论(0编辑  收藏  举报