jvm優化—— 圖解垃圾回收 原 薦

從這篇開始我們開始探討一些jvm調優的問題。在jvm調優中一個離不開的重點是垃圾回收,當垃圾回收成爲系統達到更高併發量的瓶頸時,我們就需要對jvm中如果進行“自動化”垃圾回收技術實施必要的監控和調節。

這是jvm優化系列第一篇,其他請看以下:

對於調優之前,我們必須要了解其運行原理,java 的垃圾收集Garbage Collection 通常被稱爲“GC”,它誕生於1960年 MIT 的 Lisp 語言,經過半個多世紀,目前已經十分成熟了。因此本篇主要從這三個方面來了解:

1. 哪些對象需要被回收?

2. 什麼時候回收?

3. 如何回收?

 

一、誰要被回收

java虛擬機在執行java程序的過程中會把它所管理的內存劃分爲若干個不同是數據區域,這些區域有各自各自的用途。主要包含以下幾個部分組成:

 

1、程序計數器

程序計數器佔用的內存空間我們可以忽略不計,它是每個線程所執行的字節碼的行號指示器。

2、虛擬機棧

java的虛擬機棧是線程私有的,生命週期和線程相同。它描述的是方法執行的內存模型。同時用於存儲局部變量、操作數棧、動態鏈接、方法出口等。

3、本地方法棧

本地方法棧,類似虛擬機棧,它調用的是是native方法。

4、堆

堆是jvm中管理內存中最大一塊。它是被共享,存放對象實例。也被稱爲“gc堆”。垃圾回收的主要管理區域

5、方法區

方法區也是共享的內存區域。它主要存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器(jit)編譯後的代碼數據。

 

以上就是jvm在運行時期主要的內存組成,我們看到常見的內存使用不但存在於堆中,還會存在於其他區域,雖然堆的管理對程序的管理至關重要,但我們不能只侷限於這一個區域,特別是當出現內存泄露的時候,我們除了要排查堆內存的情況,還得考慮虛擬機棧的以及方法區域的情況。

知道了要對誰以及那些區域進行內存管理,我還需要知道什麼時候對這些區域進行垃圾回收。

 

二、什麼時候回收

 

在垃圾回收之前,我們必須確定的一件事就是對象是否存活?這就牽扯到了判斷對象是否存活的算法了。

 

引用計數算法

給對象中添加一個引用計數器,每當有一個地方引用它時,計數器+1,當引用失效,計數器-1.任何時刻計數器爲0的對象就是不可能再被使用的。

優點:實現簡單,判定效率高效,被actionscript3和python中廣泛應用。

缺點:無法解決對象之間的相互引用問題。java沒有采納

 

可達性分析算法:

通過一系列稱爲“GC Roots”的對象作爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈,當一個對象到GCRoots沒有任何引用鏈相連的時候,則證明此對象是不可用的。

比如如下,右側的對象是到GCRoot時不可達的,可以判定爲可回收對象。

 

在java中,可以作爲GCRoot的對象包括以下幾種:

* 虛擬機棧中引用的對象。

* 方法區中靜態屬性引用的對象。

* 方法區中常量引用的對象。

* 本地方法中JNI引用的對象。

基於以上,我們可以知道,噹噹前對象到GCRoot中不可達時候,即會滿足被垃圾回收的可能。

那麼是不是這些對象就非死不可,也不一定,此時只能宣判它們存在於一種“緩刑”的階段,要真正的宣告一個對象死亡。至少要經歷兩次標記:

第一次:對象可達性分析之後,發現沒有與GCRoots相連接,此時會被第一次標記並篩選。

第二次:對象沒有覆蓋finalize()方法,或者finalize()方法已經被虛擬機調用過,此時會被認定爲沒必要執行。

 

三、如何回收

 

上述的兩點講解之後,我們大概明白了,哪些對象會被回收,以及回收的依據是什麼,但回收的這個工作實現起來並不簡單,首先它需要掃描所有的對象,鑑別誰能夠被回收,其次在掃描期間需要 ”stop the world“ 對象能被凍結,不然你剛掃描,他的引用信息有變化,你就等於白做了。

 

分代回收

我們從一個object1來說明其在分代垃圾回收算法中的回收軌跡。

 

1、object1新建,出生於新生代的Eden區域。

2、minor GC,object1 還存活,移動到Fromsuvivor空間,此時還在新生代。

3、minor GC,object1 仍然存活,此時會通過複製算法,將object1移動到ToSuv區域,此時object1的年齡age+1。

4、minor GC,object1 仍然存活,此時survivor中和object1同齡的對象並沒有達到survivor的一半,所以此時通過複製算法,將fromSuv和Tosuv 區域進行互換,存活的對象被移動到了Tosuv。

5、minor GC,object1 仍然存活,此時survivor中和object1同齡的對象已經達到survivor的一半以上(toSuv的區域已經滿了),object1被移動到了老年代區域。

6、object1存活一段時間後,發現此時object1不可達GcRoots,而且此時老年代空間比率已經超過了閾值,觸發了majorGC(也可以認爲是fullGC,但具體需要垃圾收集器來聯繫),此時object1被回收了。fullGC會觸發 stop the world。

 

在以上的新生代中,我們有提到對象的age,對象存活於survivor狀態下,不會立即晉升爲老生代對象,以避免給老生代造成過大的影響,它們必須要滿足以下條件纔可以晉升:

1、minor gc 之後,存活於survivor 區域的對象的age會+1,當超過(默認)15的時候,轉移到老年代。

2、動態對象,如果survivor空間中相同年齡所有的對象大小的綜合和大於survivor空間的一半,年級大於或等於該年級的對象就可以直接進入老年代。

以上採用分代垃圾收集的思想,對一個對象從存活到死亡所經歷的歷程。期間,在新生代的時刻,會用到複製算法,在老年代時,有可能會用到標記-清楚算法(mark-sweep)算法或者標記-整理算法,這些都是垃圾回收算法基於不同區域的實現,我們看下這幾種回收算法的實現原理。

 

垃圾回收算法

 

標記清除法(Mark-Sweep)

標記清除法是垃圾回收算法的思想基礎。標記清除算法將垃圾分爲兩個階段:標記階段和清除階段。

標記階段,通過根節點,標記所有從根節點開始的可達對象,未標記過的對象就是未被引用的垃圾對象。

清除階段,清除所有未被標記的對象。

  

複製算法(Copying)

複製算法是,將原有的內存空間分爲兩塊,每次只使用其中一塊,在垃圾回收時,將正在適用的內存中存活對象複製到未使用的內存塊,然後清除使用的內存塊中所有的對象。

 

標記壓縮算法(Mark-Compact)

標記壓縮算法是一種老年代的回收算法。

標記階段和標記清除算法一致,對可達對象做一次標記。

清理階段,爲了避免內存碎片產生,將所有的存活對象壓縮到內存的一端。

 

四、垃圾收集器

垃圾收集器是內存回收的具體實現,不同的廠商提供的垃圾收集器有很大的差別,一般的垃圾收集器都會作用於不同的分代,需要搭配使用。以下是各種垃圾收集器的組合方式:

 

各種組合的優缺點:

 

新生代GC策略

年老代GC策略

說明

組合1

Serial

Serial Old

Serial和Serial Old都是單線程進行GC,特點就是GC時暫停所有應用線程。

組合2

Serial

CMS+Serial Old

CMS(Concurrent Mark Sweep)是併發GC,實現GC線程和應用線程併發工作,不需要暫停所有應用線程。另外,當CMS進行GC失敗時,會自動使用Serial Old策略進行GC。

組合3

ParNew

CMS

使用-XX:+UseParNewGC選項來開啓。ParNew是Serial的並行版本,可以指定GC線程數,默認GC線程數爲CPU的數量。可以使用-XX:ParallelGCThreads選項指定GC的線程數。

如果指定了選項-XX:+UseConcMarkSweepGC選項,則新生代默認使用ParNew GC策略。

組合4

ParNew

Serial Old

使用-XX:+UseParNewGC選項來開啓。新生代使用ParNew GC策略,年老代默認使用Serial Old GC策略。

組合5

Parallel Scavenge

Serial Old

Parallel Scavenge策略主要是關注一個可控的吞吐量:應用程序運行時間 / (應用程序運行時間 + GC時間),可見這會使得CPU的利用率儘可能的高,適用於後臺持久運行的應用程序,而不適用於交互較多的應用程序。

組合6

Parallel Scavenge

Parallel Old

Parallel Old是Serial Old的並行版本

 

組合7

G1GC

G1GC

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC        #開啓

-XX:MaxGCPauseMillis =50                  #暫停時間目標

-XX:GCPauseIntervalMillis =200          #暫停間隔目標

-XX:+G1YoungGenSize=512m            #年輕代大小

-XX:SurvivorRatio=6                            #倖存區比例

 

以上優缺點來自:http://www.importnew.com/23752.html

 

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