Java虛擬機器OOM之虛擬機器棧和本地方法棧溢出(4)

來源:互聯網
上載者:User

標籤:虛擬機器棧和本地方法棧   溢出   

一、在 JAVA 虛擬機器規範中,對虛擬機器棧這個地區規定了兩種異常狀況:

(1)如果線程請求的棧深度大於虛擬機器所允許的深度,將拋出StackOverflowError 異常;
(2)如果虛擬機器棧可以動態擴充(當前大部分的 JAVA 虛擬機器都可動態擴充,只不過 JAVA 虛擬機器規範中也允許固定長度的虛擬機器棧),當擴充時無法申請到足夠的記憶體時會拋出 OutOfMemoryError 異常。
(3)與虛擬機器棧一樣,本地方法棧地區也會拋出 StackOverflowError 和OutOfMemoryError 異常。

二、前一篇文章中的第一張圖也看出來了對於虛擬機器棧和本地方法棧 如果在多線程的情況下是可能出現OOM的,下邊就是一個單線程的案例。示範一下:

/** * 設定  VM Args: -Xss128k * @author xuliugen * */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;        }    }}

要設定VM Args: -Xss128k(上一篇已經說到:設定棧為128k),結果如下:

stack length:40550Exception in thread "main" java.lang.StackOverflowError    at com.lc.oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)    後續很多異常省略。。。

結果表明:在單個線程下,無論是由於棧幀太大,還是虛擬機器棧容量太小,當記憶體無法分配的時候,虛擬機器拋出的都是 StackOverflowError 異常,而不是OOM。

三、如果測試時不限於單線程,通過不斷地建立線程的方式倒是可以產生記憶體溢出異常。自己可以建立多個線程,進行測試,但是:由於在Windows 平台的虛擬機器中, Java 的線程是映射到作業系統的核心線程上的,所以多線程代碼執行時有較大的風險,可能會導致作業系統假死。所以。。。

不過結果肯定是,多線程的情況下,是會出現OOM的!

原理如下:

為什嗎多線程的情況下就會產生OOM,這樣產生的記憶體溢出異常與棧空間是否足夠大並不存在任何聯絡,或者準確地說,在這種情況下,給每個線程的棧分配的記憶體越大,反而越容易產生記憶體溢出異常。

原因其實不難理解,作業系統分配給每個進程的記憶體是有限制的,譬如 32 位的 Windows 限制為 2GB。虛擬機器提供了參數來控制 Java 堆和方法區的這兩部分記憶體的最大值。剩餘的記憶體為 2GB(作業系統限制)減去 Xmx(最大堆容量),再減去 MaxPermSize(最大方法區容量),程式計數器消耗記憶體很小,可以忽略掉。如果虛擬機器進程本身耗費的記憶體不計算在內,剩下的記憶體就由虛擬機器棧和本地方法棧“瓜分”了。每個線程分配到的棧容量越大,可以建立的線程數量自然就越少,建立線程時就越容易把剩下的記憶體耗盡。

更簡單理解的就是:有一個作業系統為2G,我們分配給兩個線程,每個800M,也就還剩400M,這樣的話,有一個線程不夠用的話,就會在400裡邊申請,所以如果剩下的越多,出現OOM的可能性越小,如果每個分配950M,這樣就剩100M,這樣的話出現OOM的可能性就更大。如果在增加線程,系統對每一個線程非配的記憶體是一定的,所以剩下的記憶體更少,這樣的話,出現OOM的可能更大,但這都是相對而說。

遇到OOM這時候我們應該怎麼做:

如果是建立過多線程導致的記憶體溢出,在不能減少線程數或者更換 64 位元虛擬機器的情況下,就只能通過減少最大堆和減少棧容量來換取更多的線程。如果沒有這方面的經驗,這種通過“減少記憶體”的手段來解決記憶體溢出的方式會比較難以想到。這種拆東牆補西牆的方法,還是自己意會吧。

Java虛擬機器OOM之虛擬機器棧和本地方法棧溢出(4)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.