Java虛擬機內存溢出異常

    前幾天讀《深入理解Java虛擬機》測試了一下書中所寫的java虛擬機異常的代碼,特在此整理一下。

Java堆溢出

    衆所周知,JVM(java虛擬機)中堆是用於存放對象實例的,想要令其發生溢出,只需要不斷創造對象便可。
    代碼如下:

public class HeapOOM {

    static class OOMObject {}

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

}

運行結果:

java.lang.OutOfMemoryError: Java heap space

棧溢出

    java中棧分爲兩類:Java虛擬機棧和本地方法棧,java虛擬機棧爲java虛擬機的方法提供服務,而本地方法棧則是爲虛擬機使用的Native方法提供服務。二者的溢出方式均相同,都可分爲兩種:

  • 線程請求深度大於虛擬機允許的最大深度,拋出StackOverflowError異常
  • 虛擬機擴展棧時無法申請到足夠的內存空間,就會拋出OutOfMemeoryError異常

    棧深度溢出的代碼如下:

public class JavaVMStackSOF {

    private int stackLength = 1;

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

    public static void main(String[] args) throws Throwable {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:"+oom.stackLength);
            throw e;
        }
    }

}

運行結果:

stack length:9506
 *      Exception in thread "main" java.lang.StackOverflowError

棧容量溢出:
    此處書中代碼有問題,本人未能成功測試(畢竟是國人寫的書,質量不過關)。真正的測試代碼日後另行附上。。。

運行時常量池溢出

    java虛擬機中運行時常量池是java虛擬機中方法區的一部分,用於存放編譯期生成的各類字面量和符號引用。
    想要使運行時常量池溢出,需要用到String.intern()這個Native方法。該方法的作用是:如果池中包含此String對象的字符串,則返回池中這個字符串的String對象;否則將此對象所包含的字符串添加到常量池中,並返回此String對象的引用。
    代碼如下

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

}

運行結果“

java.lang.OutOfMemoryError: PermGen space

方法區溢出

    方法區用於存放Class的相關信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。這個測試基本方法是產生大量的類去填充方法區。
    但由於這個測試書中借用了CGLib項目,本人手上無此項目,故未做測試,先將代碼附上吧:

public class JavaMethodAreaOOM{
    public static void main(String[] args){
        while(true){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor(){
                public Object intercept(Object obj,Method method,Object args,MethodProxy proxy) throws Throeable{
                    return proxy.invokeSuper(obj,args);
                }
            });
            enchaner.create();
        }
    }
    static class OOMObject {}
}

本機直接內存溢出

    本機直接內存拋出異常的代碼如下:

public class DirectMemoryOOM {

    private static final int _1MB = 1024*1024;

    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);
        }
    }

}

運行結果爲:

java.lang.OutOfMemoryError
發佈了20 篇原創文章 · 獲贊 2 · 訪問量 7600
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章