性能測試-GC問題整理

年輕代與老年代的調優(筆記整理)

幾個常見名詞

年輕代(young 區)
從年輕代空間(包括Eden和Survivor 區域)回收內存被稱爲 Minor GC
空間過小可能致使對象直接進入 old區 。若是old區 滿了,會觸發full gc。但也不能過大,過大會引發回收耗時過長,致使應用阻塞。java

老年代(old 區)
從老年代GC稱爲Major GC
空間太小會產生old區小碎片,放不下大對象,引發頻繁full gc。若是用了緩存,old區也要適當大些,同時緩存不該無限增加。算法

存活區(Survivor)
Survivor的存在乎義,就是減小被送到老年代的對象,進而減小Full GC的發生。數組

伊甸園(Eden)
整個堆內存(heap)=young+old緩存

GC(垃圾回收機制)spa

堆區有兩個Survivor區,新建的對象會存活在在Eden中。Eden區若是沒有足夠的空間時會引起一次young區的GC。對象

在經歷一次MinorGC以後,Eden中的存活對象就會被移動到第一塊survivor space-S0,此時Eden被清空;blog

等Eden區再次填滿,就再觸發一次Minor GC,Eden和S0中的存活對象又會被複制送入第二塊survivor space-s1;此時S0和Eden被清空,而後下一輪S0與S1交換角色。
若是 Survivor的空間不足或經歷16次Minor GC還能在新生代中存活的對象會經過分配擔保機制被送入老年代。進程

老年代負責分配擔保讓Survivor沒法容納的對象直接進入老年代。若是剩餘空間小於轉移對象大小,將直接進行 FullGc內存

 

進入老年代的對象ci

  • 大對象會直接進入老年代(避免頻繁複制)
  • 在程序中長期持有了對象的引用(對象年齡達到指定閾值也會進入老年代)
  • survivor 區過小,只能進入老年代

FullGC

執行 Minor GC(年輕代GC) 的時候,JVM 會檢查老年代中最大連續可用空間是否大於了當前新生代全部對象的總大小
若是大於,則直接執行 Minor GC(年輕代GC)(這個時候執行是沒有風險的)
若是小於,JVM 會檢查是否開啓了空間分配擔保機制,若是沒有開啓則直接改成執行Full GC
若是開啓擔保機制,則 JVM 會檢查老年代中最大連續可用空間是否大於歷次晉升到老年代中的平均大小,若是小於則執行改成執行Full GC
若是大於則會執行 Minor GC(年輕代GC),若是 Minor GC(年輕代GC) 執行失敗則會執行 Full GC

出現Full GC的時候常常伴隨至少一次的Minor GC,但不絕對。Major GC的速度通常會比Minor GC慢10倍以上

 

內存溢出

老年代只有在新生代對象轉入及建立大對象、大數組時纔會出現空間不足的現象。當執行Full GC後空間仍然不足,則會拋出以下錯誤:
java.lang.OutOfMemoryError: Java heap space

 

GC頻率監控

  • jstat -class  類加載統計
  • jstat -compiler  編譯統計
  • jstat -GC  垃圾回收統計
  • jstat -gccapacity  堆內存統計
  • jstat -gccnew  年輕代垃圾回收統計
  • jstat -gccold  老年代垃圾回收統計
  • jstat -gcnewcapacity  年輕代內存統計
  • jstat -gcoldcapacity  老年代內存統計
  • jstat -gcmetacapacity  元空間內存統計
  • jstat -gcutil  gc總體統計
  • jstat -gccause  gc緣由

 

 

 

 

 

 

 ps -eo pid,tty,user,comm,lstart,etime | grep 【pid】 查看進程運行時間

  • YGCT :從應用程序啓動到採樣時年輕代中 gc 所用時間(s)
  • FGC :從應用程序啓動到採樣時 old  代(fullgc)gc 次數
  • FGCT :從應用程序啓動到採樣時 old  代(fullgc)gc 所用時間(s)
  • GCT :從應用程序啓動到採樣時 gc 用的時間(s)
  • YGC/YGCT=年輕代單次gc時間
  • FGC/FGCT=fullGC單次時間
  • YGC/time=年輕代gc頻率
  • FGC/time=老年代gc頻率

判斷fullgc是否正常的標準:FGCT/FGC<=200ms

 

fullGC 頻繁出現的可能緣由

  • 對象引用長期未釋放
  • survivor 區過小
  • old 區過小
  • System.gc()方法的調用

Full GC調優辦法
1:讓對象在Minor GC階段被回收、讓對象在新生代多存活一段時間及不要建立過大的對象及數組

2:年輕代小對象儘可能多,大對象則儘量直接進入老年代。年輕代因爲使用標記複製算法進行回收內存,速度很快

3:Eden區若是沒有足夠的空間時會引起一次young區的GC,經過-XX:SurvivorRatio 進行調整 Eden 和 Survivor 比例大小。少許對象的存活,適合複製算法(年輕代),大量對象存活,適合標記清理或者標記壓縮(年老代)。

相關文章
相關標籤/搜索