虛擬機系列 | 執行引擎和垃圾回收

本文源碼:GitHub·點這裏 || GitEE·點這裏

一、執行引擎

應用程序經過編譯,轉換爲字節碼文件,字節碼加載到內存空間並不能直接在操作系統上執行,執行引擎作爲Java虛擬機核心的組成部分,作用就是將字節碼指令解釋/編譯爲對應系統平臺上的本地機器指令。

解釋器:虛擬機啓動時會根據預定義對字節碼採用逐行解釋的方式執行,將每條字節碼文件中的內容解釋爲對應系統平臺的本地機器指令執行;

JIT編譯器:虛擬機將源代碼編譯成本地機器平臺相關的機器語言,並且尋找熱點高頻執行的代碼將其放入元空間中,即元空間中存放的JIT緩存代碼;

垃圾回收:對於沒有任何引用的對象標記爲垃圾,會被回收釋放內存空間。

二、垃圾對象標記

1、引用計數法

每個對象保存一個整型引用計數器,用來記錄對象被引用的次數,當該對象被一個對象引用時,計數器加1,當失去一個引用時,計數器減1;引用計數算法就是通過判斷對象的引用數量來決定對象是否可以被當做垃圾對象回收掉。

雖然引用計數法效率高,但是當兩個對象互相引用時會導致這兩個對象一直不會被回收,這是一個致命的缺陷。所以JVM並沒有採用該標記算法。

2、可達性分析算法

可達性分析算法是基於對象到根對象的引用鏈是否可達來判斷對象是否可以被回收;

運行程序把所有的引用關係鏈看作一張圖,通過GC-Roots根對象對象集合作爲起始點,從每個根節點向下不斷搜索被根對象集合所連接的對象是否可達,搜索路徑稱爲引用鏈(Reference-Chain),如果對象到GC-Roots沒有任何引用鏈存在,則說明此對象是不可用的,

  • 虛擬機棧中引用的對象;
  • 元空間中類靜態屬性引用的對象;
  • 元空間中常量引用的對象;
  • 本地方法棧中Native方法引用的對象;

相對於引用計數法算法,可達性分析算法則避免了循環引用導致的問題,同樣具備執行高效的特點,也是JVM採用的標記算法。

三、垃圾回收機制

1、標記清除算法

標記-清除算法分爲標記和清除兩個階段:

標記階段:從根對象集合進行掃描,對存活的對象對象標記;清除階段:再次掃描發現未被標記的對象並進行回收;

該算法效率不高,進行垃圾回收需要暫停應用程序,同時會產生大量內存碎片,後續程序運行過程中分配內存佔用較大的對象時,會有連續內存不夠情況,容易觸發再一次垃圾收集動作。

2、標記整理算法

標記整理算法的標記過程類似標記清除算法,第一階段:標記出垃圾對象;第二階段:讓所有存活的對象都向內存區一端移動;第三階段:直接清理掉邊界端以外的內存,類似於磁盤整理的過程;

該垃圾回收算法效率不高,對象移動過程需要暫停應用程序,適用於對象存活率高的場景(老年代)。

3、複製算法

複製算法將內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊,當使用的這塊的內存用完,就將還存活着的對象複製到另外一塊空閒內存上,然後使用過的內存空間一次清理。

該算法實現簡單,運行效率高,但是內存空間嚴重浪費,適用於對象存活率低的場景,比如新生代。

4、分代收集算法

當前市場上幾乎所有的虛擬機都採用該回收算法,分代收集算法根據年輕代和老年代的各自特點採用不同的算法機制,不同內存區域中對象生命週期也不同,因此對堆內存不同區域採用不同的回收策略可以提高垃圾回收執行效率。通常情況新生代對象存活率低,回收頻繁,就採用複製算法;老年代存對象生命週期長,活率高,就用標記清除算法或者標記整理算法。

Java堆內存一般可以分爲新生代、老年代和永久代三個模塊,如下圖所示:

新生代

通常情況下,新創建的對象實例首先都是放在新生代空間中,所以追求快速的回收掉垃圾對象,一般情況下,新生代內存按照8:1:1的比例分爲一個eden區和兩個survivor(survivor0,survivor1)區,對象實例大部分在Eden區中生成;

垃圾回收時先把eden區存活對象複製到S0區,然後清空eden區,當S0區也滿時,再將eden區和S0區存活對象複製到S1區,然後清空eden和S0區,之後交換S0區和S1區的角色,當S1區無法存放eden區和S0區的存活對象時,就將存活對象直接存移到老年代區,當老年代區也滿了,觸發一次FullGC,即新生代、老年代都進行回收。

老年代

老年代區存放一些生命週期較長的對象,對象實例在新生代中經歷了多次垃圾回收仍然存活的對象,會被移動到老年代區中。

四、源代碼地址

GitHub·地址
https://github.com/cicadasmile/java-base-parent
GitEE·地址
https://gitee.com/cicadasmile/java-base-parent

推薦閱讀:編程體系整理

序號 項目名稱 GitHub地址 GitEE地址 推薦指數
01 Java描述設計模式,算法,數據結構 GitHub·點這裏 GitEE·點這裏 ☆☆☆☆☆
02 Java基礎、併發、面向對象、Web開發 GitHub·點這裏 GitEE·點這裏 ☆☆☆☆
03 SpringCloud微服務基礎組件案例詳解 GitHub·點這裏 GitEE·點這裏 ☆☆☆
04 SpringCloud微服務架構實戰綜合案例 GitHub·點這裏 GitEE·點這裏 ☆☆☆☆☆
05 SpringBoot框架基礎應用入門到進階 GitHub·點這裏 GitEE·點這裏 ☆☆☆☆
06 SpringBoot框架整合開發常用中間件 GitHub·點這裏 GitEE·點這裏 ☆☆☆☆☆
07 數據管理、分佈式、架構設計基礎案例 GitHub·點這裏 GitEE·點這裏 ☆☆☆☆☆
08 大數據系列、存儲、組件、計算等框架 GitHub·點這裏 GitEE·點這裏 ☆☆☆☆☆
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章