1. 程式人生 > >聊聊JAVA虛擬機中的垃圾收集器

聊聊JAVA虛擬機中的垃圾收集器

垃圾收集器 JAVA虛擬機 內存區域模型 Parallel GC CMS GC

前言

JAVA虛擬機的垃圾收集器是虛擬機內存的清道夫,它的存在讓JAVA開發人員能將更多精力投入到業務研發上。了解垃圾收集器,並利用好這個工具,能更好的保障服務穩定性。這篇文章通過分析JAVA虛擬機內存模型,介紹垃圾收集器常用算法和收集器類別,使得垃圾收集器的配置和使用變得不再遙不可及。

JAVA虛擬機內存模型

JAVA虛擬機內存可以劃分為:虛擬機棧、本地方法棧、JAVA堆內存、方法區(包含運行時常量池)、程序計數器、直接內存。

虛擬機棧

虛擬機棧是線程私有的,生命周期跟線程相同。也就是說一個線程被創建後,虛擬機為其分配了一個獨立的棧幀來存儲線程的局部變量、操作數、動態鏈接、方法出口等信息,當線程結束後,該棧幀也會被回收清理。

本地方法棧

本地方法棧是虛擬機的native方法執行期間使用的一個棧幀。

JAVA堆內存

堆內存是被所有線程共享的一塊區域,用來存放對象實例和數組,屬於內存中最大的一塊區域,也是垃圾收集的主要區域。從垃圾收集的角度看,堆內存經常分為新生代和老年代。

方法區

方法區也是被所有線程共享的一塊區域,用來存儲被虛擬機加載的類信息、常量、靜態變量、JIT編譯後代碼等數據。也可以成為永久代。

程序計數器

程序計數器是線程私有的,作為當前線程所執行的字節碼的行號指示器,每個線程有一個程序計數器,用於記錄CPU切換線程時記錄當前線程的執行位置,以便下次繼續從當前位置往下執行。

直接內存

這塊不屬於JAVA虛擬機內存,但使用頻繁,也可稱之為“堆外內存”

JAVA虛擬機垃圾收集器

根據上述對JAVA虛擬機內存區域模型的介紹,我們知道JAVA程序中的對象實例都存儲在JAVA堆內存中,因此垃圾收集主要也是針對堆內存進行。為了更好的管理JAVA對象實例,並結合對象實例的生存時間長短,JAVA虛擬機將堆內存分為新生代和老年代,分別存儲剛創建不久的對象和存活較長時間的對象實例,並采用分代收集的策略分別回收新生代和老年代的內存。

內存分配與回收策略

  • 1、 分代收集思路。根據JAVA對象的生存周期特點,虛擬機將堆內存分為新生代和老年代,並分別采用新生代和老年代的垃圾回收策略。
  • 2、 新生代細分為Eden區和兩個Survivor區(即From區和To區)。大多數新生對象創建頻繁,且存活時間短,為了提高新生代區域垃圾收集效率,新創建的對象存放在Eden區,當Eden區快滿的時候,虛擬機對其觸發一次Minor GC,將新生代存活對象移動到From區,原來From區的對象根據存活年齡決定放到To區還是老年代,然後清空Eden區和From區,接著將To區對象全部移到From區。
  • 3、 大對象直接進入老年代,可以配置新生代對象的最大值,對象超過這個值就直接進入老年代。
  • 4、 發起Minor GC前,會先判斷老年代最大可用連續空間是否大於新生代對象占用的空間,如果小於或不允許冒險,則觸發一次Full GC。

    垃圾收集算法(3種基本算法)

  • 1、 復制算法。針對於新生代的垃圾收集算法。當新生代Eden區快滿的時候,將Eden區對象復制到From區,將From區對象根據存活年齡決定復制到To區還是到老年代,然後清除Eden區和From區,接著將To區對象復制到From區。
  • 2、 標記-清除算法。垃圾收集算法標記出需要回收的對象,標記完成後直接統一回收。垃圾收集器使用可達性分析來判斷哪些對象是否存活,通過設置一系列GC Roots節點(包括棧、方法區中的靜態屬性和常量所引用的對象,以及本地方法棧中引用的對象),從這類節點往下搜索,當對象不在GC Root節點的引用鏈上時,說明對象不可達,可以被回收。
  • 3、 標記-整理算法。垃圾收集算法標記出需要回收的對象,標記完成後將存活對象往內存的一端移動,然後直接清理掉端邊界以外的內存。

    常用垃圾收集器

    由於虛擬機中的垃圾收集是分代收集的,新生代和老年代的垃圾收集策略不太一樣,所以一般是使用針對新生代和老年代的垃圾收集器組合。

  • 1、 Serial GC。新生代收集器,采用復制算法,用於Client客戶端新生代垃圾收集,針對內存占用較少的應用進行垃圾收集。
  • 2、 Serial Old GC。老年代收集器,采用標記-整理算法,用於Client客戶端老年代垃圾收集,針對內存占用較少的應用進行垃圾收集。
  • 3、 Parallel Scavenge GC。新生代收集器,采用復制算法,並行收集新生代內存垃圾,可以設置垃圾收集器的吞吐量,還可以設置自動適配調節吞吐量。
  • 4、 Parallel New GC。新生代收集器,采用復制算法,並行收集新生代內存垃圾。
  • 5、 Parallel Old GC。老年代收集器,采用標記-整理算法,並行收集老年代內存垃圾。
  • 6、 CMS GC。老年代收集器,采用標記-清除算法,並行收集老年代內存垃圾,不整理內存。由於在執行垃圾收集期間不中斷業務線程,所以容易產出“浮動垃圾”,導致Full GC。可以通過設置參數來觸發內存整理任務。
  • 7、 G1 GC。不再將堆內存區分新生代和老年代,而是將堆內存看作若幹個均分小區域,並對最空閑的內存區域進行標記和回收。適用於大內存的應用。

聊聊JAVA虛擬機中的垃圾收集器