若是對象已經死亡了,就能夠進行回收,判斷方式以下java
1).引用計數器:給對象添加一個計數器,有地方引用,就+1,當引用失效,就-1。當計數器爲0時,判斷對象不能再使用,可是當對象相互引算法
用的時候沒法進行GC數據結構
1).可達性算法:從GC Roots開始,到對象之間有引用鏈相連,就是可達的。HotSpot採用可達性算法,商用虛擬機沒有采用引用計數器jvm
GC Roots有哪些:spa
1).局部變量表中引用的對象線程
2).棧幀中常量引用的對象對象
3).棧幀中static引用的對象生命週期
4).JNI引用的對象內存
5).類加載器字符串
6).Thread
1).標記清除:對不具備可達性的對象進行標記,而後進行統一回收,最基本的GC算法
缺點:標記和清除兩個階段效率都不高,會產生大量不連續的內存碎片,在給大對象分配內存的時候,可能沒法找到連續的內存,而不得不提
前進行GC
2).複製:把內存分紅相同兩部分,每次使用一部分,GC的時候把可用對象複製到另外一邊,而後把使用的一邊直接清理掉,不會產生內存碎片,
可是直接浪費了一半內存,代價太巨大了。
3).標記整理:若是對象存活率比較高的時候,複製算法的效率就會下降,並且須要有額外的空間進行分擔擔保,老年代就不可能使用對存活
對象進行標記以後,而後把存活的對象都向一端移動,直接清理邊界之外的內存
4).分帶收集:當前商用VM採用的GC算法,新生代使用複製算法,老年代使用另外兩個。
商用虛擬機的新生代都是採用複製算法,新生代的對象98%生命週期都很短,每次使用Eden Space和From Survivor,把這兩塊區域存活的對象
複製到To Survivor,而後清理內存,Eden Space:From Survivor=8:1,這樣每次只會浪費10%內存,當To Survivor內存空間不夠的時候,使用老年
代。
可達性分析從GC Roots節點找引用鏈時,會發生GC停頓,是指分析期間中止其餘全部的線程,若是分析過程當中對象引用關係還在變化,準確性
沒法獲得保證。
主流jvm採用準確式GC,HotSpot中經過一組OopMap的數據結構知道哪些地方存放着對象引用,就能夠快速、準確完成GC枚舉。
新生代和老生代默認的空間佔比分別是是1/三、2/3。
複製算法的執行流程以下
一、把Eden + From Survivor存活的對象放入To Survivor區;
二、清空Eden和From Survivor分區;
三、From Survivor和To Survivor分區交換。
四、每次在From Survivor到To Survivor移動時都存活的對象,年齡就+1,當年齡到達15(默認配置是15)時,升級爲老年代。大對象也會
直接進入老年代。
老年代當空間佔用到達某個值以後就會觸發全局垃圾收回,通常使用標記整理的執行算法。
方法區回收:(jdk1.8以前永久帶實現了方法區,而在jdk1.8廢棄永久帶,經過本地內存實現)
對方法區回收也能夠說是對永久帶回收,主要針對兩部分:
一、廢棄的常量:例如一個字符串"abc"在常量池中,可是沒有任何String對象引用它,進行GC的話,就須要被清理出常量池,類、方法、字段
的符號引用也是相同的
二、無用的類:
1).該類的全部實例都已經被GC
2).加載該類的ClassLoader被GC
3).該類對應java.lang.class對象沒有被任何地方引用,也就是沒法經過反射獲得該類的方法。
就是自己保存的數據是另外一塊內存的起始地址
分類:
一、強引用:相似於new一個對象對應的引用,只要具備可達性,不會被回收
二、軟引用:軟引用關聯的對象,在內存溢出發生之前,這些對象會被回收。能夠經過SoftReference實現軟引用
三、弱引用:只能活到下次GC以前,當進行垃圾回收的時候,它確定死了。能夠經過WeakReference實現軟引用
四、虛引用:最弱的一種引用關係。爲對象設置虛引用惟一目的就是能在對象被GC的時候收到一個系統通知。能夠經過PhantPhantomReference
實現軟引用