1. 程式人生 > >Java垃圾回收概覽

Java垃圾回收概覽

引用計數 AR ner 一次 一半 vivo HA finalize 這一

GC要解決三個主要的問題:

  • 哪些內存需要回收?
  • 什麽時候回收?
  • 如何回收?

哪些內存需要回收?

最簡單的是引用計數(reference count),缺陷是無法解決循環引用。於是更快點的算法是可達性分析(reachable analysis)。

什麽時候回收?

至少要經歷兩次標記過程:

  1. 在進行可達性分析後,發現沒有與GC roots相連接的引用鏈時,會被第一次標記並進行一次篩選——是否有必要執行finalize()。
    • 對象沒有finalize()方法或者被虛擬機執行過,視為“沒必要執行”
    • 有必要執行finalize(),被放置於F-Queue隊列中,並在稍後由(虛擬機自動建立的、優先級低的)Finalizer線程去“執行”(觸發相應方法,但並不會等待它完成)。
  2. 之後GC將對F-Queue中對象進行第二次小規模的標記。

如何回收?

  1. Mark-Sweep(標記-清除):(缺陷:會造成大量的內存碎片。)
  2. Copy:內存一分為二,每次只使用其中的一半。清理時,將存活對象拷貝到未使用的另一半,再將已用的這一半清理掉。(缺陷:將內存縮小為原來的一半,在存活對象較多時效率很低。所以在新生代區域會使用這種算法,一大塊Eden和兩塊Survivor區域。每次使用Eden和其中一塊Survivor區域。)
  3. Mark-Compact(標記-整理):讓所有存活的對象,往一端移動,適用於存貨對象較多的區域,如老生代。
  4. 分代收集:綜合了以上所有方法,對不同的generation區域使用不同的算法。

參考文獻

  • 《Java垃圾回收(GC)機制詳解》
  • 《Thinking in Java》
  • 《深入理解Java虛擬機》

Java垃圾回收概覽