1、GC觸發的條件
觸發的條件有兩種:(1)程序調用System.gc()時可以觸發;(2)系統自身來決定GC觸發的時機。
2、jvm內存分配
(1)對象分配:
優先在Eden區分配:在大多數情況下,對象在新生代Eden區中分配,當Eden區中沒有足夠空間的分配時,系統調用一次Minor GC,將Eden中存活的對象和其中一塊survivor中存活的對象移動到另一塊的survivor區域,如果在Minor GC期間發現新生代存活對象無法放入空閒的survivor區,則會通過空間分配擔保機制使對象提前進入老年代。
大對象直接進入老年代:某些收集器提供了-XX:PretenureSizeThreshold的參數,大於該值的大對象直接在老年代分配,避免在Eden區和Survivor區之間產生大量的內存複製(例:需要大量連續內存的JAVA對象),因此大對象導致還有不少空閒內存就提前觸發GC以獲取足夠的連續空間。
(2)對象晉升:
年齡閾值:VM爲每個對象定義了對象年齡(Age)計數器,對象在Eden出生並經過第一次Minor GC之後仍存活,且被Survivor區中每經過一次Minor GC後Age就+1,當增加到一定程度(MaxTenuringThreshold),將會晉升老年代。
提前晉升:若在Survivor空間中相同年齡所有對象大小的總和大於Survivor空間的一半,年齡大於或等於該年齡的對象就可以直接進入老年代。
3、jvm對象生死判定(何時回收)
在java語言,都是通過可達性分析算法(並沒有採用引用計數法,引用計數法無法解決循環引用的問題)進行對象存活與否的判定:通過稱之爲GC Root是的對象作爲起點,然後向下搜索,搜索走過的路徑稱之爲引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時,即說明該對象不可達。
在java中,可作爲GC Roots的對象包括:
(1)方法區:類靜態屬性引用的對象;
(2)方法區:常量引用的對象;
(3)虛擬機棧(本地變量表)中引用的對象;
(4)本地方法棧JNI(Native方法)中引用的對象;