1. 程式人生 > >java虛擬機器記憶體分配之新生代與老年代GC

java虛擬機器記憶體分配之新生代與老年代GC

1. Java堆中各代分佈:

圖1:Java堆中各代分佈

Young:主要是用來存放新生的物件。

Old:主要存放應用程式中生命週期長的記憶體物件。

Permanent:是指記憶體的永久儲存區域,主要存放Class和Meta的資訊,Class在被 Load的時候被放入PermGen space區域. 它和和存放Instance的Heap區域不同,GC(Garbage Collection)不會在主程式執行期對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤。

2. JVM 使用的GC演算法是什麼?

分代收集。

即將記憶體分為幾個區域,將不同生命週期的物件放在不同區域裡;

在GC收集的時候,頻繁收集生命週期短的區域(Young area);

比較少的收集生命週期比較長的區域(Old area);

基本不收集的永久區(Perm area)。

3. GC 和 Full GC 有什麼區別?

GC(或Minor GC):收集 生命週期短的區域(Young area)。

Full GC (或Major GC):收集生命週期短的區域(Young area)和生命週期比較長的區域(Old area)對整個堆進行垃圾收集。

他們的收集演算法不同,所以使用的時間也不同。 GC 效率也會比較高,我們要儘量減少 Full GC 的次數。 當顯示呼叫System.gc() 時,gc does a full collection(both young generation and tenured generation).

4. Minor GC後,Eden是空的嗎?

是的,Minor GC會把Eden中的所有活的物件都移到Survivor區域中,如果Survivor區中放不下,那麼剩下的活的物件就被移到Old generation 中。

5. Garbage collection options(JDK1.4):

圖2:GC引數

堆設定  
-Xms :初始堆大小  
-Xmx :最大堆大小  
-XX:NewSize=n :設定年輕代大小  
-XX:NewRatio=n: 設定年輕代和年老代的比值。如:為3,表示年輕代與年老代比值為1:3,年輕代佔整個年輕代年老代和的1/4  
-XX:SurvivorRatio=n :年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區佔整個年輕代的1/5 
-XX:MaxPermSize=n :設定持久代大小  
收集器設定  
-XX:+UseSerialGC :設定序列收集器  
-XX:+UseParallelGC :設定並行收集器  
-XX:+UseParalledlOldGC :設定並行年老代收集器  
-XX:+UseConcMarkSweepGC :設定併發收集器  
垃圾回收統計資訊  
-XX:+PrintHeapAtGC GC的heap詳情 
-XX:+PrintGCDetails  GC詳情 
-XX:+PrintGCTimeStamps  列印GC時間資訊 
-XX:+PrintTenuringDistribution    列印年齡資訊等 -XX:+HandlePromotionFailure   老年代分配擔保(true  or false) 並行收集器設定  
-XX:ParallelGCThreads=n :設定並行收集器收集時使用的CPU數。並行收集執行緒數。  
-XX:MaxGCPauseMillis=n :設定並行收集最大暫停時間  
-XX:GCTimeRatio=n :設定垃圾回收時間佔程式執行時間的百分比。公式為1/(1+n)  
併發收集器設定  
-XX:+CMSIncrementalMode :設定為增量模式。適用於單CPU情況。  
-XX:ParallelGCThreads=n :設定併發收集器年輕代收集方式為並行收集時,使用的CPU數。並行收集執行緒數。

6. 例子:Heap size 設定

場景:在JAVA_HOME下demo/jfc/SwingSet2/目錄下執行下面的命令:

    java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar

系統輸出:

Exception in thread "Image Fetcher 0" java.lang.OutOfMemoryError: Java heap space

Exception in thread "Image Fetcher 3" java.lang.OutOfMemoryError: Java heap space

Exception in thread "Image Fetcher 1" java.lang.OutOfMemoryError: Java heap space

Exception in thread “Image Fetcher 2” java.lang.OutOfMemoryError: Java heap space

調優:將-Xms和-Xmx選項設定為32m,而-Xmn為1/4的-Xmx值。

結果:執行java -jar –Xmn8m –Xms32m -Xmx32m SwingSet2.jar,系統正常執行。

7. JVM  Runtime Data Area(執行時資料區):

圖3:JVM執行時資料區(一)

Heap: JVM只有一個為所有執行緒所共享的堆,所有的類例項和陣列都是在堆中建立的。

Method area: JVM只有一個為所有的執行緒所共享的方法區。它儲存類結構,例如執行時常量池,成員和方法資料以及方法、構造方法的程式碼。

Java Stacks:每個JVM執行緒擁有一個私有的棧。

Pc registers: JVM可以同時支援執行多個執行緒,因此每個執行緒需要各自的PC(program counter)暫存器。

Native method stacks: 儲存native方法進入區域的地址 。

 

圖4:JVM執行時資料區(二)

Heap和Method area被所有執行緒共享,其生存期和JVM的生存期相同;Java Stacks、Pc registers、Native method stacks被每個執行緒獨自擁有,其生存期和執行緒的生存期相同。

8. 常見的記憶體洩露錯誤

很多開發人員都碰到過java.lang.OutOfMemoryError的錯誤。這種錯誤又分兩種:java.lang.OutOfMemoryError: Java heap space和java.lang.OutOfMemoryError: PermGen space。引起這種錯誤的原因可能是程式問題,也可能是是JVM引數配置問題引起的。若是引數問題,前者可以同過配置-Xms和-Xmx引數來設定,而後者可以通過配置 -XX:PermSize和-XX:MaxPermSize來設定。

9. 參考資料:

1.  A brief history of garbage collection –

2.  Garbage collection in the HotSpot JVM –

3.  Tuning Garbage Collection with the 5.0 JavaTM Virtual Machine

4.  Diagnosing a GC problem –