記一次StackOverflowError

目錄

一、遇見StackOverflowError的準備

二、StackOverflowError的心動歷程


背景:StackOverflowError(譯爲:堆棧溢出錯誤)當然平時我們稱之爲內存溢出。在回顧LinkedList集合源碼時偶然遇到了該錯誤,由此興趣大發,吟詩作樂(寫博作樂)一發。

先祝各位媽媽母親節快樂,回想上一次母親節,彷彿就在昨天~

一、遇見StackOverflowError的準備

StackOverflowError,在偶然的一次Node節點的相互追加中心動。心動過程來圖

 代碼如下

public class StackOverflowErrorDemo {

    private static class Node<E> {

        /** 當前元素值 (HZ)*/
        E item;
        /** 當前元素的上一個元素 (HZ)*/
        Node<E> next;
        /** 當前元素的下一個元素 (HZ)*/
        Node<E> prev;
        /** 單參構造 @param element 當前元素的值 (HZ)*/
        Node(E element) {
            this.item = element;
        }
    }

    public static void main(String[] args) {
        Node<String> node1 = new Node<>("節點一");
        Node<String> node2 = new Node<>("節點二");
        node1.next = node2;
        node2.prev = node1;
    }
}

通過DeBug調試,能看到走到最後一行時,出現了內存溢出異常, 原因爲當執行完node2.prev = node1時,無限循環的添加鏈路就開始了,node2不斷增加變大導致異常。

二、StackOverflowError的心動歷程

那麼執行邏輯是怎麼樣的呢?PS:下圖中綠色區域代碼JVM內存大小。舉例子。當前實際情景遠不止這麼大。

第一步執行時,往內存中存放了一個值“第一關”,此時JVM內存佔據四分之一。

第二步執行時,往內存中存放了新的值“第二關”,此時JVM內存佔據四分之二。

第三步執行時,node1追加了Next等於node2,那麼node1就會擴大一倍。此時JVM佔據四分之三。

第四步執行時,node2也追加了prev等於node1,那麼node2也會擴大一倍、此時JVM佔據慢。

重點:理論上上面四步是走完了所有的過程沒有問題,但是實際上程序的引用依賴鏈不允許它這樣走完,因爲node1與node2是循環依賴鏈,那麼程序底層需要將這個依賴鏈不斷的延續下去。故由此衍生第五步

第五步:在第四步追加了node1的node2之後,node1又需要追加node2作爲下一個的引用依賴,故在JVM內存中,node1繼續追加node2,此時JVM內存已經超過原有值,故拋出異常。當然如果JVM內存夠大,會一直不斷的擴大下去,直到內存溢出,拋出異常爲止。

綜上,JVM內存就可比做是一個容器瓶子,當容器被數據塞滿時,即拋出了內存溢出異常。

故若再次面對內存溢出類似的問題產生時,舉一個生動形象的栗子即可。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章