Java垃圾回收概覽
阿新 • • 發佈:2018-06-17
引用計數 AR ner 一次 一半 vivo HA finalize 這一
GC要解決三個主要的問題:
- 哪些內存需要回收?
- 什麽時候回收?
- 如何回收?
哪些內存需要回收?
最簡單的是引用計數(reference count),缺陷是無法解決循環引用。於是更快點的算法是可達性分析(reachable analysis)。
什麽時候回收?
至少要經歷兩次標記過程:
- 在進行可達性分析後,發現沒有與GC roots相連接的引用鏈時,會被第一次標記並進行一次篩選——是否有必要執行finalize()。
- 對象沒有finalize()方法或者被虛擬機執行過,視為“沒必要執行”
- 有必要執行finalize(),被放置於F-Queue隊列中,並在稍後由(虛擬機自動建立的、優先級低的)Finalizer線程去“執行”(觸發相應方法,但並不會等待它完成)。
- 之後GC將對F-Queue中對象進行第二次小規模的標記。
如何回收?
- Mark-Sweep(標記-清除):(缺陷:會造成大量的內存碎片。)
- Copy:內存一分為二,每次只使用其中的一半。清理時,將存活對象拷貝到未使用的另一半,再將已用的這一半清理掉。(缺陷:將內存縮小為原來的一半,在存活對象較多時效率很低。所以在新生代區域會使用這種算法,一大塊Eden和兩塊Survivor區域。每次使用Eden和其中一塊Survivor區域。)
- Mark-Compact(標記-整理):讓所有存活的對象,往一端移動,適用於存貨對象較多的區域,如老生代。
- 分代收集:綜合了以上所有方法,對不同的generation區域使用不同的算法。
參考文獻:
- 《Java垃圾回收(GC)機制詳解》
- 《Thinking in Java》
- 《深入理解Java虛擬機》
Java垃圾回收概覽