Java虛擬機內存溢出異常--《深刻理解Java虛擬機》學習筆記及我的理解(三)

Java虛擬機內存溢出異常--《深刻理解Java虛擬機》學習筆記及我的理解(三)

書上P39java

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());
        }
    }
}

 會內存溢出, 輸出結果以下:atom

若是是用下面這段代碼的話, 是不會內存溢出的. 由於有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());
        }
    }
}

 輸出結果以下(下面部分結果可能根據機器環境不一樣而不一樣):  3d

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. 直接內存溢出

這段代碼我這裏沒有運行出書上的效果...blog

書上的意思應該是, 設定了直接內存大小最大爲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);
        }
    }
}
相關文章
相關標籤/搜索