成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java內(nèi)存區(qū)域及內(nèi)存溢出

cheukyin / 2925人閱讀

摘要:直接通過可以造成本機(jī)內(nèi)存溢出。小節(jié)內(nèi)存區(qū)域描述異常程序計(jì)數(shù)器略略略虛擬機(jī)棧存放編譯器可知的各種基本類型,對(duì)象引用和類型每個(gè)線程的棧大小堆存放對(duì)象實(shí)例最大值最小值運(yùn)行時(shí)常亮池存放編譯期生成的字面量和符號(hào)引用,運(yùn)行期也能放入常量池。

堆溢出

Java堆用于存儲(chǔ)對(duì)象實(shí)例,只要不斷地創(chuàng)建對(duì)象,并且保證GC Roots到對(duì)象之間有可達(dá)路徑避免垃圾回收,當(dāng)?shù)竭_(dá)最大堆的容量限制后就會(huì)產(chǎn)生Java.lang.OutOfMemoryError.

/**
 * VM Options:
 * -Xms20M
 * -Xmx20M
 * -XX:+HeapDumpOnOutOfMemoryError
 */
public class HeapOOM{
    static class OOMObject{}
    
    public static void main(String[] args){
        List list = new ArrayList();
        while(true){
            list.add(new OOMObject());
        }
    }
}

結(jié)果:
GC多次執(zhí)行后觸發(fā)OutOfMemoryError.

棧溢出

關(guān)于虛擬機(jī)棧,在Java規(guī)范中描述了兩種異常:

如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的最大深度,將拋出StackOverflowError異常。

如果虛擬機(jī)在擴(kuò)展棧時(shí)無法申請(qǐng)到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常。

然而,在單線程下,虛擬機(jī)在??臻g不足時(shí)會(huì)嘗試擴(kuò)展??臻g,因此,當(dāng)無法繼續(xù)分配時(shí),到底是內(nèi)存太小,還是已使用的??臻g太大,其實(shí)是一回事。在實(shí)驗(yàn)中,單線程環(huán)境下,只會(huì)拋出StackOverflowError異常。

/**
 * VM Option:
 * -Xss160K
 */
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;
        }
    }
}

結(jié)果:

操作系統(tǒng)分配給每個(gè)進(jìn)程的內(nèi)存是有限制的,通常為操作系統(tǒng)限制總內(nèi)存-最大堆容量(Xmx)-最大方法區(qū)容量(MaxPermSize)-程序計(jì)數(shù)器消耗。每個(gè)線程分配到的棧容量越大,可以建立的線程數(shù)目越小。

/**
 * VM Options:
 * -Xss2M
 */
public class JavaVMStackOOM{
    private void dontStop(){
        while(true){}
    }
    
    public void stackLeakByThread(){
        while(true){
            Thread thread = new Thread(new Runnable(){
                @Override
                public void run(){
                    dontStop();
                }
            });
            thread.start();
        }
    }
    
    public static void main(String[] args) throws Throwable{
        JavaVMStackOOM oom = new JavaVMStackOOM();
        oom.stackLeakByThread();
    }
}

結(jié)果:
Exception in thread "main" java.lang.outOfMemoryError: unable to create new native thread

運(yùn)行時(shí)常量池溢出

運(yùn)行時(shí)常量池在JDK 1.6及之前版本中在方法區(qū)中,在1.7及之后轉(zhuǎn)移至堆空間。在JDK 1.6及之前版本中可以通過限制方法區(qū)大小,從而間接限制運(yùn)行時(shí)常量池大小。

/**
 * ONLY WORKS BEFORE JDK 1.7
 * VM Options:
 * -XX:PermSize=10M
 * -XX:MaxPermSize=10M
public class RuntimeConstantPoolOOM{
    public static void main(String[] args){
        List list = new ArrayList();
        int i = 0;
        while(true){
            list.add(String.valueof(i++).intern());
        }
    }
}

結(jié)果:
Exception in thread "main" java.lang.OutOfMemoryError:PermGen space

方法區(qū)溢出

方法區(qū)用于存放Class相關(guān)信息,因此要使得方法區(qū)溢出,除了在JDK 1.7之前使運(yùn)行時(shí)常量池溢出外,基本的思路是運(yùn)行時(shí)生成大量的類去填滿方法區(qū)。
結(jié)果
Exception in thread "main" java.lang.OutOfMemoryError:PermGen space

直接內(nèi)存(DirectMemory)溢出

直接內(nèi)存不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分。在JDK 1.4中新加入了NIO(New Input/Output)類,引入了一種基于通道(Channel)與緩沖區(qū)(Buffer)的I/O方式,使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存。
DirectMemory容量可通過-XX: MaxDirectMemorySize指定,如果不指定,則默認(rèn)與Java堆最大值一樣(-Xmx)。直接通過allocateMemory可以造成本機(jī)內(nèi)存溢出。

結(jié)果:
Exception in thread "main" java.lang.OutOfMemoryError
直接內(nèi)存溢出的一個(gè)特征是Heap Dump文件中不會(huì)看先明顯的異常指示。如果OOM之后Dump文件很小,而程序中又直接或間接使用了DIO,就應(yīng)該檢查是否直接內(nèi)存溢出。

String.intern()

String.intern()是一個(gè)Native方法,作用是:如果字符串常量池中已經(jīng)包含一個(gè)等于此String對(duì)象的字符串,則返回代表池中這個(gè)字符串的String對(duì)象,否則,將此String對(duì)象包含的字符串添加到常量池中,并且返回此String對(duì)象的引用。

public class RuntimeConstantPoolOOM{
    public static void main(String[] args){
        String str1 = new StringBuilder("計(jì)算機(jī)").append("軟件").toString();
        System.out.println(str1.intern() == str1);//JDK 1.6 false JDK 1.7 true
        
        String str2 = new StringBuilder("ja").append("va").toString();
        System.out.println(str2.intern() == str2);//JDK 1.6 false JDK 1.7 true
    }
}

在JDK 1.6中,intern()方法會(huì)把首次遇到的字符串實(shí)例復(fù)制到永久代(方法區(qū)運(yùn)行時(shí)常量池),返回的是這個(gè)永久代中這個(gè)字符串實(shí)例的引用,而由StringBuilder創(chuàng)建的字符串實(shí)例在Java堆上,所以必然不是同一個(gè)引用。
在JDK 1.7中,intern()實(shí)現(xiàn)不會(huì)再?gòu)?fù)制,只是在常量池中記錄首次出現(xiàn)的實(shí)例引用,因此intern()返回的引用和由StringBuilder創(chuàng)建的那個(gè)字符串實(shí)例是同一個(gè)。

小節(jié)
內(nèi)存區(qū)域 描述 VM Option 異常
程序計(jì)數(shù)器
虛擬機(jī)棧 存放編譯器可知的各種基本類型,對(duì)象引用和returnAddress類型 -Xss160K 每個(gè)線程的棧大小 StackOverflowError/OutOfMemoryError
Java堆 存放對(duì)象實(shí)例 -Xms10M 最大值
-Xmx20M 最小值
OutOfMemory: Java heap space
運(yùn)行時(shí)常亮池 存放編譯期生成的字面量和符號(hào)引用,運(yùn)行期也能放入常量池(string.intern())。JDK 1.7之前在方法區(qū)中,JDK 1.7及之后移至堆中 隨方法區(qū)或堆設(shè)置 OutOfMemoryError
方法區(qū) 存儲(chǔ)虛擬機(jī)加載的類信息、常亮、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù),又稱為永久代(Permanent Generation) -XX:PermSize=10M 初始值
-XX:MaxPermSize=20M 最大值
OutOfMemoryError: PermGen space
直接內(nèi)存 在JDK 1.4中加入NIO類,直接分配堆外內(nèi)存 -XX:MaxDirectMemorySize=10M,
如果不指定默認(rèn)與-Xmx一樣
OutOfMemoryError

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69402.html

相關(guān)文章

  • 【修煉內(nèi)功】[JVM] 淺談虛擬機(jī)內(nèi)存模型

    摘要:也正是因此,一旦出現(xiàn)內(nèi)存泄漏或溢出問題,如果不了解的內(nèi)存管理原理,那么將會(huì)對(duì)問題的排查帶來極大的困難。 本文已收錄【修煉內(nèi)功】躍遷之路 showImg(https://segmentfault.com/img/bVbsP9I?w=1024&h=580); 不論做技術(shù)還是做業(yè)務(wù),對(duì)于Java開發(fā)人員來講,理解JVM各種原理的重要性不必再多言 對(duì)于C/C++而言,可以輕易地操作任意地址的...

    sanyang 評(píng)論0 收藏0
  • 關(guān)于JVM內(nèi)存溢出的原因分析解決方案探討

    摘要:內(nèi)存溢出分配的內(nèi)存空間超過系統(tǒng)內(nèi)存。內(nèi)存泄漏的原因分析由大塊組成堆,棧,本地方法棧,程序計(jì)數(shù)器,方法區(qū)。內(nèi)存溢出的原因分析內(nèi)存溢出是由于沒被引用的對(duì)象垃圾過多造成沒有及時(shí)回收,造成的內(nèi)存溢出。小結(jié)棧內(nèi)存溢出程序所要求的棧深度過大導(dǎo)致。 showImg(https://segmentfault.com/img/bVbweuq?w=563&h=300); 前言:JVM中除了程序計(jì)數(shù)器,其他...

    xuexiangjys 評(píng)論0 收藏0
  • JVM內(nèi)存模型與運(yùn)行時(shí)數(shù)據(jù)區(qū)域

    摘要:內(nèi)存模型和運(yùn)行時(shí)數(shù)據(jù)區(qū)域的關(guān)系主內(nèi)存對(duì)應(yīng)著堆,工作內(nèi)存對(duì)應(yīng)著棧。在的單例模式中有運(yùn)用到二運(yùn)行時(shí)數(shù)據(jù)區(qū)域內(nèi)存區(qū)域因?yàn)榈倪\(yùn)行時(shí)數(shù)據(jù)區(qū)域一直在改善,所以不同版本之間會(huì)有不同。 一、java內(nèi)存模型 showImg(https://segmentfault.com/img/remote/1460000016694250?w=1810&h=941); java定義內(nèi)存模型的目的是:為了屏蔽各種...

    canopus4u 評(píng)論0 收藏0
  • JVM系列(一):深入詳解JVM 內(nèi)存區(qū)域總結(jié)!

    摘要:一內(nèi)存區(qū)域虛擬機(jī)在運(yùn)行時(shí),會(huì)把內(nèi)存空間分為若干個(gè)區(qū)域,根據(jù)虛擬機(jī)規(guī)范版的規(guī)定,虛擬機(jī)所管理的內(nèi)存區(qū)域分為如下部分方法區(qū)堆內(nèi)存虛擬機(jī)棧本地方法棧程序計(jì)數(shù)器。前言 在JVM的管控下,Java程序員不再需要管理內(nèi)存的分配與釋放,這和在C和C++的世界是完全不一樣的。所以,在JVM的幫助下,Java程序員很少會(huì)關(guān)注內(nèi)存泄露和內(nèi)存溢出的問題。但是,一旦JVM發(fā)生這些情況的時(shí)候,如果你不清楚JVM內(nèi)存的...

    Aldous 評(píng)論0 收藏0
  • 十種JVM內(nèi)存溢出的情況,你碰到過幾種?

    摘要:內(nèi)存溢出的情況就是從類加載器加載的時(shí)候開始出現(xiàn)的,內(nèi)存溢出分為兩大類和。以下舉出個(gè)內(nèi)存溢出的情況,并通過實(shí)例代碼的方式講解了是如何出現(xiàn)內(nèi)存溢出的。內(nèi)存溢出問題描述元空間的溢出,系統(tǒng)會(huì)拋出。這樣就會(huì)造成棧的內(nèi)存溢出。 導(dǎo)言: 對(duì)于java程序員來說,在虛擬機(jī)自動(dòng)內(nèi)存管理機(jī)制的幫助下,不需要自己實(shí)現(xiàn)釋放內(nèi)存,不容易出現(xiàn)內(nèi)存泄漏和內(nèi)存溢出的問題,由虛擬機(jī)管理內(nèi)存這一切看起來非常美好,但是一旦...

    ShevaKuilin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<