jvm虛擬機內(nèi)存模型及垃圾回收算法

jvm是什么,百度百科這樣寫道:
虛擬機是一種抽象化的計算機,通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的。Java虛擬機有自己完善的硬體架構(gòu),如處理器、堆棧、寄存器等,還具有相應(yīng)的指令系統(tǒng)。Java虛擬機屏蔽了與具體操作系統(tǒng)平臺相關(guān)的信息,使得Java程序只需生成在Java虛擬機上運行的目標代碼(字節(jié)碼),就可以在多種平臺上不加修改地運行。
簡單通俗的說,jvm類似一個中間件,為程序和各個操作系統(tǒng)之間架起了一個橋梁,不需要為特定的系統(tǒng)編寫特定的代碼。

jvm內(nèi)存模型

jvm主要包括五大模塊,類裝載器子系統(tǒng)、運行時數(shù)據(jù)區(qū)、執(zhí)行引擎、本地方法接口和垃圾收集模塊。
在本節(jié)中主要講解運行時數(shù)據(jù)區(qū)的數(shù)據(jù)結(jié)構(gòu)。


1.png
  • 程序計數(shù)器
  1. 是線程私有的,各個線程之間計數(shù)器互不影響,獨立存儲
  2. 如果線程執(zhí)行的是java方法,則記錄的是正在執(zhí)行的虛擬機字節(jié)碼指令的地址;如果執(zhí)行的是Native方法,這個計數(shù)器值為空。
  3. 是唯一一個在jvm規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域
  • 虛擬機棧
  1. 線程私有的,生命周期與線程相同
  2. 當執(zhí)行一個方法時,都會創(chuàng)建一個棧幀
  3. 可以存儲局部變量表、操作數(shù)棧、動態(tài)鏈接和方法出口等


    2.png
  • 本地方法棧
  1. 線程私有的
  2. 與虛擬機棧的作用類似,當執(zhí)行Native方法時會用到
  • java堆
  1. 是內(nèi)存管理中最大的一塊
  2. 存放的是對象的實例和數(shù)組對象
  3. java堆按照生命周期的不同,劃分為新生代和老年代。當新生代中經(jīng)過多次垃圾回收仍然存活的對象九華轉(zhuǎn)化成老年代 。
  4. 年輕代又分為Eden和Survivor區(qū)。Survivor區(qū)由FromSpace和ToSpace組成。Eden區(qū)占大容量,Survivor兩個區(qū)占小容量,默認比例是8:1:1
  5. 新生成的對象首先放到年輕代Eden區(qū),當Eden空間滿了,觸發(fā)Minor GC,存活下來的對象移動到Survivor0區(qū),Survivor0區(qū)滿后觸發(fā)執(zhí)行Minor GC,Survivor0區(qū)存活對象移動到Suvivor1區(qū),這樣保證了一段時間內(nèi)總有一個survivor區(qū)為空。經(jīng)過多次Minor GC仍然存活的對象移動到老年代。
  6. 老年代存儲長期存活的對象,占滿時會觸發(fā)Major GC = Full GC,GC期間會停止所有線程等待GC完成,
  7. 將對象根據(jù)存活概率進行分類,對存活時間長的對象,放在固定區(qū),從而減少掃描垃圾時間及GC頻率,針對分類進行不同的垃圾回收算法。
  8. 在新生代中,每次垃圾收集中都會發(fā)現(xiàn)大批對象死去,只有少量存活,所有采用了復(fù)制算法
  9. 而老年代中因為對象存活率高,沒有額外空間對它進行分配擔保,就必須使用“標記--清理”或者“標記--整理“算法進行回收。


    3.png
  • 方法區(qū)
  1. 是各個線程共享的內(nèi)存區(qū)域
  2. 非堆內(nèi)存,用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量等。
  3. 在jdk1.8中廢除了方法區(qū),替代是元空間,它的本質(zhì)和方法區(qū)類似,但它并不在虛擬機中,而是在本地內(nèi)存中,默認情況下,元空間的大小僅受本地內(nèi)存的限制。

HotSpot虛擬機對象

  1. 虛擬機遇到一條new指令時,首先將去檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用,并且檢查這個符號引用代表的類是否已被加載、解析和初始化過,如果沒有,那必須先執(zhí)行相應(yīng)的類加載過程。
  2. 在為新生對象分配空間時,主要有兩種方式。指針碰撞空閑列表
  3. 并發(fā)情況下的對象創(chuàng)建問題。為了保證操作的正確性,一種采取對分配內(nèi)存空間的動作進行同步處理-實際上虛擬機采用CAS配上失敗重試的方法保證更新操作的原子性;另一種是把內(nèi)存分配的動作按照線程劃分到不同的空間之中進行,即每個線程在java堆中預(yù)先分配一小塊內(nèi)存,稱為本地線程分配緩沖(TLAB)。哪個線程要分配內(nèi)存,就在哪個線程的TLAb上分配,只有TLAB用完并分配新的TLAB時,才需要同步鎖定。
    4.png
  • 對象的內(nèi)存布局
    在hotspot虛擬機中,主要分為3塊區(qū)域:對象頭、實例數(shù)據(jù)和對齊填充
    對象頭主要分為兩部分信息,一部分是存儲對象自身的運行時數(shù)據(jù),另一部分是類型指針。
5.png
  • 對象的訪問定位
    java程序通過棧上的reference數(shù)據(jù)來操作堆上的具體對象。它是一個指向?qū)ο蟮囊?,但如何通過這個引用去定位、訪問堆中的具體對象,這是不確定的,取決于虛擬機的類型。當前主要有兩種方式:使用句柄直接指針
  1. 使用句柄,會在java堆中劃分出一塊內(nèi)存來作為句柄池,在句柄中包含了對象實例數(shù)據(jù)和對象類型數(shù)據(jù)的地址信息。
6.png
  1. 使用直接指針訪問,在reference中存儲的是對象地址,在對象實例數(shù)據(jù)中存儲了到對象類型數(shù)據(jù)的指針。
    7.png

垃圾回收

利用垃圾收集器對堆進行回收前,首先要確定的是哪些對象還存活著,哪些對象已經(jīng)“死去”。
起初典型的算法是引用計數(shù)算法 ,它為每個對象添加一個引用計數(shù)器,每當有一個地方引用它時,計數(shù)器就加1;當引用失效時,計數(shù)器就減1,當計數(shù)器為0時就是不可能再被使用了。但在某些情況下會出現(xiàn)一些錯誤,當對象間有相互循環(huán)引用時,會相互引用著對方,導致它們的引用計數(shù)都不為0。
可達性分析算法
該算法通過一系列的稱為“GC Roots”的對象作為起始點,從這些節(jié)點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時,則證明此對象是不可用的。

8.png

在java語言中,可作為GC Roots的對象有下面幾種:

  • 虛擬機棧(棧幀中的本地變量表)中的引用對象
  • 方法區(qū)中類靜態(tài)屬性引用的對象
  • 方法區(qū)中常量引用的對象
  • 本地方法棧JNI(即一般說的Native方法)引用的對象
    一個對象真正死亡,至少要經(jīng)歷兩次標記記錄
    第一次: 在進行可達性分析后發(fā)現(xiàn)沒有與GC Roots相連接的引用鏈,那它會被第一次標記并進行篩選,篩選的條件是此對象是否有必要執(zhí)行的finalize()方法。當對象沒有覆蓋finalize()方法或者finalize()方法已經(jīng)被虛擬機調(diào)用過,虛擬機將這兩種情況都視為“沒有必要執(zhí)行”。
    第二次: 當這個對象被判定為有必要執(zhí)行finalize()方法 ,那么這個對象將會放置在一個F-Queue的隊列中,如果該對象重新與引用鏈上的任意一個對象建立關(guān)聯(lián)時,它就可以從“即將回收”的集合中移除。

垃圾回收算法

  1. 標記-清除算法
    首先標記出所有需要回收的對象,在標記完成后統(tǒng)一回收所有所標記的對象
9.png
  1. 復(fù)制算法
    它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊,當這一塊的內(nèi)存用完時,就將還存活的對象復(fù)制到另外一塊上,然后再把已使用過的內(nèi)存空間一次清理掉。
10.png
  1. 標記-整理算法
    當標記完待回收對象后,讓所有存活的對象都向一端移動,然后直接清理掉端邊界意外的內(nèi)存,
    不是直接對可回收對象進行清理。
    [站外圖片上傳中...(image-ff210b-1563195408545)]
  2. 分代收集算法
    新生代采用復(fù)制算法,在老年代采用“標記-清除”或者“標記-整理”算法。新生代分為Eden區(qū)和兩個相同大小的Survivor區(qū),
    所有新創(chuàng)建的對象都分配在Eden區(qū)域中。當Eden區(qū)域滿后會觸發(fā)minor GC,將Eden區(qū)仍然存活的對象復(fù)制到其中一個Survivor區(qū)域中,另外一個Survivor區(qū)中的存活對象也復(fù)制到這個Survivor區(qū)域中,并始終保持一個Survivor區(qū)是空的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容