Java虛擬機--GC 算法(基礎篇) - GC參考手冊

3. GC 算法(基礎篇) - GC參考手冊

2017年01月13日 12:16:12 鐵錨 閱讀數:5580更多

所屬專欄: GC性能優化

相關術語翻譯說明:

Mark,標記;

Sweep,清除;

Compact,整理; 也有人翻譯爲壓縮,譯者認爲GC時不存在壓縮這回事。

Copy,複製; copy 用作名詞時一般翻譯爲拷貝/副本,用作動詞時翻譯爲複製。

注: 《垃圾回收算法手冊》將 Mark and Sweep 翻譯爲: 標記-清掃算法; 譯者認爲 標記-清除 更容易理解。

您應該已經閱讀了前面的章節:

  1. 垃圾收集簡介 - GC參考手冊
  2. Java中的垃圾收集 - GC參考手冊

本章簡要介紹GC的基本原理和相關技術, 下一章節再詳細講解GC算法的具體實現。各種垃圾收集器的實現細節雖然並不相同,但總體而言,垃圾收集器都專注於兩件事情:

  • 查找所有存活對象
  • 拋棄其他的部分,即死對象,不再使用的對象。

第一步, 記錄(census)所有的存活對象, 在垃圾收集中有一個叫做 標記(Marking) 的過程專門幹這件事。

標記可達對象(Marking Reachable Objects)

現代JVM中所有的GC算法,第一步都是找出所有存活的對象。下面的示意圖對此做了最好的詮釋:

03_01_Java-GC-mark-and-sweep.png

首先,有一些特定的對象被指定爲 Garbage Collection Roots(GC根元素)。包括:

  • 當前正在執行的方法裏的局部變量和輸入參數
  • 活動線程(Active threads)
  • 內存中所有類的靜態字段(static field)
  • JNI引用

其次, GC遍歷(traverses)內存中整體的對象關係圖(object graph),從GC根元素開始掃描, 到直接引用,以及其他對象(通過對象的屬性域)。所有GC訪問到的對象都被標記(marked)爲存活對象。

存活對象在上圖中用藍色表示。標記階段完成後, 所有存活對象都被標記了。而其他對象(上圖中灰色的數據結構)就是從GC根元素不可達的, 也就是說程序不能再使用這些不可達的對象(unreachable object)。這樣的對象被認爲是垃圾, GC會在接下來的階段中清除他們。

在標記階段有幾個需要注意的點:

在標記階段,需要暫停所有應用線程, 以遍歷所有對象的引用關係。因爲不暫停就沒法跟蹤一直在變化的引用關係圖。這種情景叫做 Stop The World pause (全線停頓),而可以安全地暫停線程的點叫做安全點(safe point), 然後, JVM就可以專心執行清理工作。安全點可能有多種因素觸發, 當前, GC是觸發安全點最常見的原因。

此階段暫停的時間, 與堆內存大小,對象的總數沒有直接關係, 而是由存活對象(alive objects)的數量來決定。所以增加堆內存的大小並不會直接影響標記階段佔用的時間。

標記 階段完成後, GC進行下一步操作, 刪除不可達對象。

刪除不可達對象(Removing Unused Objects)

各種GC算法在刪除不可達對象時略有不同, 但總體可分爲三類: 清除(sweeping)、整理(compacting)和複製(copying)。下一章節將詳細講解這些算法。

Sweep(清除)

Mark and Sweep(標記-清除) 算法的概念非常簡單: 直接忽略所有的垃圾。也就是說在標記階段完成後, 所有不可達對象佔用的內存空間, 都被認爲是空閒的, 因此可以用來分配新對象。

這種算法需要使用 空閒表(free-list),來記錄所有的空閒區域, 以及每個區域的大小。維護空閒表增加了對象分配時的開銷。此外還存在另一個弱點 —— 明明還有很多空閒內存, 卻可能沒有一個區域的大小能夠存放需要分配的對象, 從而導致分配失敗(在Java 中就是 OutOfMemoryError)。

03_02_GC-sweep.png

Compact(整理)

標記-清除-整理算法(Mark-Sweep-Compact), 將所有被標記的對象(存活對象), 遷移到內存空間的起始處, 消除了標記-清除算法的缺點。 相應的缺點就是GC暫停時間會增加, 因爲需要將所有對象複製到另一個地方, 然後修改指向這些對象的引用。此算法的優勢也很明顯, 碎片整理之後, 分配新對象就很簡單, 只需要通過指針碰撞(pointer bumping)即可。使用這種算法, 內存空間剩餘的容量一直是清楚的, 不會再導致內存碎片問題。

03_03_GC-mark-sweep-compact.png

Copy(複製)

標記-複製算法(Mark and Copy) 和 標記-整理算法(Mark and Compact) 十分相似: 兩者都會移動所有存活的對象。區別在於, 標記-複製算法是將內存移動到另外一個空間: 存活區。標記-複製方法的優點在於: 標記和複製可以同時進行。缺點則是需要一個額外的內存區間, 來存放所有的存活對象。

03_04_GC-mark-and-copy-in-Java.png

請繼續閱讀下一章: 4. GC 算法(實現篇) - GC參考手冊

原文鏈接: GC Algorithms: Basics

翻譯人員: 鐵錨 http://blog.csdn.net/renfufei

翻譯時間: 2016年02月06日

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章