如何判定垃圾對象:
- 引用計數法
- 爲每一個對象添加一個引用計數器,當有地方對該對象有引用的時候,引用計數器+1,當引用失效的時候,引用計數器-1
- 直到引用計數爲0,該對象就變爲了無用的對象
- 優點:算法簡單,效率高
- 缺點:不能解決循環引用的垃圾對象的情況
- 打印GC收集的日誌配置參數:-verbose:gc -XX:+PrintGCDetails
- 可達性分析法
- 把程序在堆中創建的對象看作一張圖,以棧中GC Root爲跟,向下尋找引用對象,如果每一個對象都直接或間接的和GC Root有關聯,則不是垃圾對象;如果尋找完畢之後,和GC Root沒有關係的對象,即爲垃圾對象
- HotSpot VM採用的就是這種分析算法,大部分虛擬機都採用這種算法
- 可以解決循環依賴的垃圾對象的回收
- 什麼可以作爲GC Root呢?
- 虛擬機棧中棧幀中的局部變量表存儲的對象句柄
- 方法區的類屬性所引用的對象
- 方法區中常量所引用的對象
- 本地方法棧中引用的對象
回收策略:
- 標記-清除算法
- 利用引用計數法或者可達性分析法判定出無用的對象之後,對無用的對象進行標記,然後清空
- 缺點
- 空間問題:堆內存會產生大量的內存碎片,一方面造成了空間的浪費;
- 效率問題:二如果要分配一塊大的內存,還需要第二次觸發GC,進行兩次回收,效率低下;
- 複製算法
- 將堆區劃分爲兩個區域,先使用其中的一塊進行創建對象,垃圾回收的時候,將其中有用的對象複製到另一塊區域整理好,無用的對象不需要管,將第一塊區域全部清空
- 缺點
- 不能充分的利用內存空間
- 標記-整理算法
- 主要針對不經常回收的區域,比如老年代
- 兩塊內存區域A和B,將A中需要清楚的對象移動到B中,將B中有用的對象移動到A中,這樣一來B中就全爲垃圾對象,直接清空就可以了
- 分代收集算法
- 分代回收垃圾機制,是基於這樣一個事實:不同的對象,有不同的生命週期,因此呢,不同的生命週期的對象採用不同的回收算法,可以提高回收效率;JVM把堆內存劃分爲以下四塊:
- Eden區(新生代):所有剛創建的對象都放到Eden區域中,Eden的目的就是清除掉那些生命週期短的對象,對應Minor GC,採用效率較高的複製算法;
- Survivor1、Survivor2區(存活區):Eden區採用複製算法用到這兩個區域進行復制以及清除;
- Tenured Gen(老年代):當經歷過15次(默認)垃圾回收以然還存活的對象,將其放入老年代,老年代中存放的都是一些生命週期較長的對象,對應Major GC/Full GC(全部區域),因爲這一塊區域垃圾回收的頻率相對較低一點,因此採用標記-整理算法;
-
-
垃圾回收過程:
-
1.新創建的對象都存儲在Eden中;
2.當Eden區存儲達到一定比例之後,會觸發Minor GC,將有用的對象複製到Survivor1中,清空Eden區;
3.當Eden區再次滿之後,將Eden和Survivor1中有用的對象複製到Survivor2中,同時清空Eden區和Survivor1區;
4.當Survivor區中對象經歷過15次(默認)垃圾回收,就將其複製到Tenured Gen/Old區域中;
5.當Tenured Gen區滿了,會觸發一次Full GC,進行一次全面清理。
-
- 分代回收垃圾機制,是基於這樣一個事實:不同的對象,有不同的生命週期,因此呢,不同的生命週期的對象採用不同的回收算法,可以提高回收效率;JVM把堆內存劃分爲以下四塊: