java gc --- 关键词解释
分代gc
java的堆內存主要分為young generation與old generation,這兩塊分開回收。這就是所謂的分代gc
其中young generation又分為一個eden space與兩個survivor space(From與To)。默認情況下,eden space占young generation的80%,兩個survivor space各占10%。
young gc:新對象一般在eden space中分配,如果eden space滿了,就進行一次。eden space + From 中的所有存活對象會被復制到To里去(這是因為大部分的新分配對象都會迅速死亡,每個survivor space雖然只占young generation的10%,但是一般情況下足夠存放young gc中的存活元素)。每次young gc之后,From與To交換。
每個Object的對象頭里都有字段用于記錄這個對象經歷了多少次young gc。如果一個對象熬過了一定次數(可以通過-XX:MaxTenuringThreshold配置,默認為15次)的Young gc而不死,那么可以晉升到old generation。
如果新對象的體積過大(可以通過-XX:PretenureSizeThreshold配置,但是該設置只對Serial和ParNew收集器生效),那么它會被直接分配到old generation
full gc:如果old generation也滿了,就會觸發full gc。full gc會對整個堆空間做gc。具體的操作是從gc root(下文介紹)出發,遍歷所有可達對象,然后回收所有不可達對象。正常情況下會回收大量的內存,如果full gc后還是無法獲得足夠分配對象的內存,就會拋出OOM錯誤。
?一般來說young gc的耗時較少(數十或者數百毫秒級別),full gc耗時較長(一般在秒級別,如果堆內存很大,甚至可以產生分鐘級別的停頓)
?
gc root
gc的起點,一組可以保證絕對存活的對象,例如:
Class - 由系統類加載器(system class loader)加載的對象,這些類是不能夠被回收的,他們可以以靜態字段的方式保存持有其它對象。我們需要注意的一點就是,通過用戶自定義的類加載器加載的類,除非相應的java.lang.Class實例以其它的某種(或多種)方式成為roots,否則它們并不是roots,.
Thread - 活著的線程
Stack Local - Java方法的local變量或參數
JNI Local - JNI方法的local變量或參數
JNI Global - 全局JNI引用
Monitor Used - 用于同步的監控對象
Held by JVM - 用于JVM特殊目的由GC保留的對象,但實際上這個與JVM的實現是有關的。可能已知的一些類型是:系統類加載器、一些JVM知道的重要的異常類、一些用于處理異常的預分配對象以及一些自定義的類加載器等。然而,JVM并沒有為這些對象提供其它的信息,因此就只有留給分析分員去確定哪些是屬于"JVM持有"的了。
?
remember set/card table/write barrier
重新考慮上文提到的young gc,我們怎樣才能知道young gen中的哪些對象是可達的?
最樸素的思想當然是從gc root出發,對整個heap中的對象進行可達性分析。這毫無疑問可以解決問題,但是如果這樣做,young gc和full gc又有什么區別呢?
所以我們需要額外的機制來記錄,old gen中的哪些對象引用了young gen中的對象。也可以理解為擴充了young gc中gc root的范圍。
Remembered Set是在實現部分垃圾收集(partial GC)時用于記錄從非收集部分指向收集部分的指針的集合的抽象數據結構。
card table是remember set的一種實現,card table實際上是一個byte數組,card table中的每個byte(也就是所謂的card)都對應了old gen中的一小塊內存(chunk,默認是512byte)。如果card table中的某個card被標記為dirty,那么這個card對應的chunk中可能存在指向young gen的對象。在young gc時,就只需要掃描gc root + old gen中的dirty chunk中的對象即可。
card table的維護是由write barrier來完成的。任何對old gen中對象的修改,都會導致這個對象所在的chunk對應的card被標記為dirty。
card table的維護會帶來一定的開銷,但是根據統計分析,它確實可以極大的減少young gc的開銷,所以還是值得的。
?
stw
stop the world,顧名思義,jvm中的所有工作線程都會暫停。此時整個java進程處于無響應狀態。
young gc與full gc都會引起stw,只是時間長短的區別
?
promotion guarantee check
本節的討論基于CMS算法
每次Minor GC執行完以后,虛擬機會檢查之前晉升到老年代的平均大小是否大于老年代的剩余空間大小,如果大于,則發起一次Full/Major GC,如果小于,則查看HandlePromotionFailure值是否允許擔保失敗,如果允許,那只會進行一次Minor GC。如果不允許失敗,那么也要改為進行一次Full/Major GC
如果young gc時,To的空間不足以存放From + Eden中的存活對象,那么這些對象會被直接移動到old gen中(即使它們的年齡還不足以提升到old gen,這個情況叫做premature promotion,中文大概叫“過早提升”,它會導致full gc頻率提高,jvm雖然盡力優化,但還是無法避免)。如果此時old gen的空間也不足,就會引發Promtion failed。Promtion failed會引發full gc。
?
concurrent?mode?failure
Concurrent Mode Failure
The CMS collector uses one or more garbage collector threads that run simultaneously with the application threads with the goal of completing the collection of the tenured generation before it becomes full. As described previously, in normal operation, the CMS collector does most of its tracing and sweeping work with the application threads still running, so only brief pauses are seen by the application threads. However, if the CMS collector is unable to finish reclaiming the unreachable objects before the tenured generation fills up, or if an allocation cannot be satisfied with the available free space blocks in the tenured generation, then the application is paused and the collection is completed with all the application threads stopped. The inability to complete a collection concurrently is referred to as concurrent mode failure and indicates the need to adjust the CMS collector parameters. If a concurrent collection is interrupted by an explicit garbage collection (System.gc()) or for a garbage collection needed to provide information for diagnostic tools, then a concurrent mode interruption is reported.
1. 如果old gen在被用完前不能完成對無引用對象的回收。
2. 如果old gen中的剩余空間不能滿足應用的內存分配需求。
上面這兩個場景會引發Concurrent Mode Failure,此時old gen的收集器會從CMS切換到Serial Old,這會引起一次有非常長的stw的full gc
?
參考資料
http://hllvm.group.iteye.com/group/topic/21468#post-272070 ??RednaxelaFX對card table的說明
http://blog-archive.griddynamics.com/2011/06/understanding-gc-pauses-in-jvm-hotspots.html ? card table + 分代gc
https://blogs.msdn.microsoft.com/abhinaba/2009/03/02/back-to-basics-generational-garbage-collection/ ? 微軟對card table的說明
http://dept.cs.williams.edu/~freund/cs434/hotspot-gc.pdf ?card table + 分代gc
https://www.yourkit.com/docs/java/help/gc_roots.jsp ?gc root都有什么?
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html ?oracle官方的gc調優文檔
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html ? oracle官方對cms的說明
轉載于:https://www.cnblogs.com/stevenczp/p/6595995.html
總結
以上是生活随笔為你收集整理的java gc --- 关键词解释的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jquery赋值和取值input,com
- 下一篇: 世界是有生命的(通向财富自由之路学习笔记