JVM基礎05-Java內存模型、JVM內存模型及Java對象模型

1. 什麼是Java內存模型(JMM)
Java內存模型(Java Memory Model ,JMM)就是一種符合內存模型規範的,屏蔽了各種硬件和操作系統的訪問差異的,保證了Java程序在各種平臺下對內存的訪問都能保證效果一致的機制及規範。
Java內存模型規定了所有的變量都存儲在主內存中,每條線程還有自己的工作內存,線程的工作內存中保存了該線程中是用到的變量的主內存副本拷貝,線程對變量的所有操作都必須在工作內存中進行,而不能直接讀寫主內存。不同的線程之間也無法直接訪問對方工作內存中的變量,線程間變量的傳遞均需要自己的工作內存和主存之間進行數據同步進行。

1.1 JMM就作用於工作內存和主存之間數據同步過程。他規定了如何做數據同步以及什麼時候做數據同步。如圖所示:

1.2 JMM的實現

在Java中提供了一系列和併發處理相關的關鍵字,比如 volatile、 synchronized、 final、 concurren包等。其實這些就是Java內存模型封裝了底層的實現後提供給程序員使用的一些關鍵字。這裏涉及到併發編程,我們需要了解併發編程的三個特性:原子性、可見性、有序性。這方面的知識我們留到併發編程那邊再詳細總結。


2. 什麼是Java對象模型
        Java內存模型包含對象頭、實例數據、對齊填充,如圖所示:

3. JVM內存模型
運行時數據區是一種規範,而Java模型是對此規範的實現。        
模型圖示:

注:前面我們總結過,非堆即方法區(JDK1.8後爲元空間)

4. 從對象的創建過程瞭解JVM內存模型
step 1:JVM在創建對象時首先會試圖在Eden區->Eden區內存不足則進行minor GC回收不活躍的對象->回收後的Eden區內存夠不夠->不夠則執行下一步
step2:survivor區內存夠?->夠則將Eden區的部分複製到s區,申請空間成功。不夠則查看old區,old區夠則將S區的部分活躍對象複製到OLD區,Eden區部分活躍對象複製到S區,申請對象空間成功。->old區不夠,則觸發FullGC->fullGC後的OLD區還是不夠則觸發OM(OutOfMemoryError)
注:minorGC--新生代GC majorGC--老年代GC --fullGC=minorGC+majorGC

5. 拓展理解問題
4.1 爲什麼需要survivor區,只有Eden區不行嗎?
        如果只有Eden區那麼就會 有很多存活對象經過minorGC後被保存到Old區,這樣Old區很快就會滿,而Old區一旦內存不足就會觸發FullGC(因爲MajorGC一般都是伴隨着minorGC的,所以可以當爲fullGC),FullGC消耗的時間比較長,效率低,會大大影響程序的響應速度。
        如果Old區內存比較小則會頻繁觸發FullGC,如果增大Old區內存則一次FullGC的時間會更長。
注:FullGC消耗時間比較長主要是Old區採用標記清除和標記清理算法,且Old區一般對象數量龐大,一次GC的消耗時間自然要比minorGC長

5.2 爲什麼需要兩個S區?
        爲了解決內存碎片化問題。Eden區滿了就會把存活對象複製到S區。下一次GC的時候Eden區和S區各有一部分存活對象,此時直接把Eden區的存活對象複製到S區,那麼這兩部分內存是很有可能不連續的,這就導致了碎片化問題。而分爲兩個S區可以保證永遠有一個S區是空的,另一個S區的內存是連續的。相當於浪費了一半的S區來解決內存的碎片化問題。

5.3 爲什麼Eden區和S1、S0比例是8:1:1?
        因爲大部分對象是“朝生夕死”的,所以Eden區應該足夠大,大多數對象都在Eden區被回收。

5.4 堆內存中都是線程共享的嗎?
        不是的。jvm默認會爲每個線程在Eden區開闢一個buffer區域,用來加速對象的分配,稱之爲TLAB(ThreadLocal Allocation Buffer),TLAB內存區域較小,對象默認會在TLAB分配內存,但是如果對象比較大,則會在堆共享內存區域中分配/

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