Java記憶體地區與類比記憶體地區異常

來源:互聯網
上載者:User

標籤:jvm記憶體   記憶體溢出   

我把Java的記憶體地區畫了一張思維導圖,以及各地區的主要功能。

類比Java堆溢出

Java堆用於儲存物件執行個體,只要不斷地建立對象並且保證GC ROOTS到對象之間有可達路徑避免被回收機制清除,就可以類比出Java堆溢出。

package hxl.insist.jvm;import java.util.ArrayList;import java.util.List;/** * 下面是JVM Args: * -Xms20m 堆的最小值 -Xmx20m 堆的最小值  (設定為一樣可避免堆自動擴充) * -XX:+HeapDumpOnOutOfMemoryError  當虛擬機器出現記憶體溢出異常時,Dump出當前的堆轉儲快照 * -XX:HeapDumpPath=E:\eclipseworkspace\UnderStandingTheJVM\hprof  設定產生的堆轉儲快照的路徑 * @author hanxl * */public class HeapOutOfMemory {    static class StuffObject {    }    static List<StuffObject> list = new ArrayList<StuffObject>();    public static void main(String[] args) {        Thread thread = new Thread(new Runnable() {            public void run() {                createObj();            }        });         thread.start();    }    private static void createObj() {        while (true) {            list.add(new StuffObject());        }    }}

用MemoryAnalyzer分析一下堆轉儲快照如:

從根項目到記憶體消耗聚集點的最短路徑,可以很清楚的看到整個引用鏈。

在上面這張圖上,我們可以清楚的看到,這個對象集合中儲存了大量內部類StuffObject 對象的引用,就是它導致的記憶體泄露。

類比Java虛擬機器棧溢出

關於虛擬機器棧,在Java虛擬機器中規範了兩種異常:

  1. 如果線程請求的棧深度大於虛擬機器所允許的最大深度,將拋出StackOverflowError異常。
  2. 如果虛擬機器地擴充棧時無法申請到足夠的記憶體空間,則拋出OutOfMemoryError異常。

類比第一種情況:

package hxl.insist.jvm;/** * 下面是JVM Args: * -Xss128k 設定棧容量大小 * @author hanxl */public class JavaVMStackSOF {    public void stackLeak() {        stackLeak();    }    public static void main(String[] args) throws Throwable {        new JavaVMStackSOF().stackLeak();    }}

類比第二種情況:

package hxl.insist.jvm;/** * 下面是JVM Args: * -Xss2M 設定棧容量大小 * @author hanxl */public class JavaVMStackOOM {    public static void main(String[] args) {        new JavaVMStackOOM().threadInvokeMethod();    }    public void threadInvokeMethod() {        while (true) {            Thread thread = new Thread(new Runnable() {                @Override                public void run() {                    infiniteLoop();                }            });            thread.start();        }    }   private void infiniteLoop() {          while (true)              ;   }}
比較兩種情況為什麼實現方式不同?

Java虛擬機器棧是線程私人的,它的生命同期與線程相同。我們把虛擬機器棧比做一個盒子,-Xss是設定盒子的大小,而一個線程只能對應一個盒子。而每個Java方法在執行的時候都會在盒子中建立一個棧幀用於儲存局部變數表等一些資訊。

所以為了製造出第一種情況下的異常,我們把盒子的大小設定小一點,使用遞迴不斷調用方法,從而撐破盒子;而為了製造出第二種情況下的異常,我們應該把盒子的大小設定小大一點,多建立一些盒子,從而讓其無法申請到足夠的記憶體空間。

只要瞭解上面那張思維導圖的記憶體地區,類比出其它記憶體地區異常也很簡單。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Java記憶體地區與類比記憶體地區異常

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.