【JVM】HotSpot JVM內存管理和GC策略總結

原文地址:http://singleant.iteye.com/blog/1308842

JVM的相關知識是學習java高級特性必須要去深入學習的。平時也有一些學習和實踐,不過總結比較少。

今天有時間總結一下最基礎的內存模型和GC策略的知識,在此記錄一下。

 

hotspot jvm內存模型

1.內存模型

hotspot的內存模型很多地方都有類似總結,我也簡單總結了一下,大概可以用下圖表示:



 關於幾個分區的描述定義

1.線程棧:線程創建是會爲每個線程創建一個線程棧,線程棧裏面會爲每個方法調用創建一個棧幀。主要用於保存線程的當前運行狀態。

2.堆:用於存放運行時中生成的新對像。會劃分成新生代和老年代。新生代裏面又劃分成了eden區、存活1區和存活2區。

3.永久區:方法和常量區,用於存放方法字節碼元數據和各種常量。

 

爲什麼堆會劃分爲新生代和老年代?

基本原理:對於大部分應用,常駐對象不多。因爲大部分存活壽命不長,新生代和老年代的劃分有利於區分對待和縮小垃圾回收範圍。(Most allocated objects are not referenced (considered live) for long, that is, they die young. Few references from older to younger objects exist.)

2.內存相關啓動參數

 

內存相關常見jvm參數
參數 含義
-Xms 最小堆空間
-Xmx 最大堆空間
-Xmn 新生代空間
-Xss 線程棧空間
-XX:PermSize=xxx 永久代空間
-XX:MaxPermSize=xxx 最大永久代空間
-XX:SurviorRatio=xxx 代表eden:s0的比例
-XX:NewRatio=xx 新生代和舊生代的比例.
-XX:MaxTenuringThreshold。 在新生代最大存活次數

hotspot 內存垃圾回收策略總結

1.內存回收策略和常見概念

常見內存回收策略可以從以下幾個維度來理解:

1.1 串行&並行 
串行:單線程執行內存回收工作。十分簡單,無需考慮同步等問題,但耗時較長,不適合多cpu。
並行:多線程併發進行回收工作。適合多CPU,效率高。
1.2 併發& stop the world 
stop the world:jvm裏的應用線程會掛起,只有垃圾回收線程在工作進行垃圾清理工作。簡單,無需考慮回收不乾淨等問題。
併發:在垃圾回收的同時,應用也在跑。保證應用的響應時間。會存在回收不乾淨需要二次回收的情況。
1.3 壓縮&非壓縮&copy 
壓縮:在進行垃圾回收後,會通過滑動,把存活對象滑動到連續的空間裏,清理碎片,保證剩餘的空間是連續的。
非壓縮:保留碎片,不進行壓縮。

copy:將存活對象移到新空間,老空間全部釋放。(需要較大的內存。)

 

一個垃圾回收算法,可以從上面幾個維度來考慮和設計,而最終產生擁有不同特性適合不同場景的垃圾回收器。

2.HotSpot JVM的YGC&FGC

YGC :對新生代堆進行GC。頻率比較高,因爲大部分對象的存活壽命較短,在新生代裏被回收。性能耗費較小。

FGC :全堆範圍的GC。默認堆空間使用到達80%(可調整)的時候會觸發FGC。以我們生產環境爲例,一般比較少會觸發FGC,有時10天或一週左右會有一次。

3.常見GC算法和jvm參數

3.1.串行垃圾收集器

新生代和老生代因爲結構劃分不一樣,其串行收集器算法也不一樣

新生代串行收集器

採用stop the world策略,步驟大概是:先從eden區掃描,把存活的對象拷貝到to區,如果to區放不下的對象直接拷貝到old區。再從from區掃描存活對象,如果對象存活次數超過閥值的就移到老年區,其他的移到to區。做完之後from和to區概念互換(from和to只是運行時的概念,其實就對應存活1區和存活2區)。

圖形的表示如下:

回收前:


 

回收後:


 

老生代串行收集器

老生代垃圾回收主要分爲三個階段 Mark-sweep-compact

Mark :識別哪些是存活的
Sweep : 識別垃圾,並回收
Compact :滑動活動對象並壓縮到連續空間,碎片整理

 

串行垃圾回收器在jvm client模式下是默認啓動的。參數 -XX:+UseSerialGC 可以設置垃圾回收策略爲串行。

 

3.2並行垃圾回收器

主要以下特點:

充分利用CPU
吞吐量優先
和串行一樣,不過是多線程執行,縮短了stop-the-world時間。
-server模式下默認的回收器。參數 -XX:+UseParallelGC 可以設置垃圾回收策略爲並行。

 

3.3並行壓縮收集器(Parallel Compacting Collector)

只對老生代適用,新生代仍舊和並行垃圾回收器一樣。

其過程大概如下:

標記階段 ,使用多線程對存在引用的對象進行並行標記。 
分析階段 ,GC對各個區域進行分析,GC認爲,在經過上次GC後,越左邊的區域,有引用的對象密度要遠遠大於右邊的區域。所以就從左往右分析,當某個區域的密度達到一個值的時候,就認爲這是一個臨界區域,所以這個臨界區域左邊的區域,將不會進行壓縮,而右邊的區域,則會進行壓縮。 
壓縮階段 ,多各個需要壓縮的區域進行並行壓縮

 

參數-XX:+UseParallelOldGC 可以設置老生代垃圾回收策略爲並行壓縮。

 

3.4 Concurrent Mark-Sweep (CMS) Collector

主要特點

仍舊是老生代適用。

減少停頓,以響應時間爲優先。

只有標記和清除,不會進行會壓縮。

初始標記和清除支持和應用程序併發執行,中間還是會有一re-mark需要stop the world。

 

參數-XX:+UseConcMarkSweepGC 可以設置老生代垃圾回收策略爲CMS。

 

3.5 G1垃圾收集器

是在JDK7裏支持的,用於取代CMS。具體具體見:http://docs.oracle.com/javase/7/docs/technotes/guides/vm/G1.html


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