年輕代(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
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頻率監控
ps -eo pid,tty,user,comm,lstart,etime | grep 【pid】 查看進程運行時間
判斷fullgc是否正常的標準:FGCT/FGC<=200ms
Full GC調優辦法
1:讓對象在Minor GC階段被回收、讓對象在新生代多存活一段時間及不要建立過大的對象及數組
2:年輕代小對象儘可能多,大對象則儘量直接進入老年代。年輕代因爲使用標記複製算法進行回收內存,速度很快
3:Eden區若是沒有足夠的空間時會引起一次young區的GC,經過-XX:SurvivorRatio 進行調整 Eden 和 Survivor 比例大小。少許對象的存活,適合複製算法(年輕代),大量對象存活,適合標記清理或者標記壓縮(年老代)。