Java記憶體回收(2)__Java

來源:互聯網
上載者:User

以下是筆者前面翻譯的記憶體回收相關文章 Hotspot GC概覽

Parallel Scavenge(並行回收)

本文我們將會描述並行記憶體回收(Parallel GC)是如何工作的。具體來說,這是一個在Eden空間運行Parallel Scavenge收集器、在老年代(Tenured generation)空間運行並行標記(Parallel Mark)和Sweep收集器的組合。你可以通過傳入參數’ -XX:+UseParallelOldGC’來擷取這些特性,雖然在某些機器類型上它是預設的。

如果你對垃圾收集器的內容還沒有一個總體的瞭解,你可以先閱讀關於記憶體回收的第一篇文章。

Eden and Survivor空間

在並行回收收集器中,eden和survivor空間的回收是使用大家所熟知的Hemispheric GC方法。對象初始分配儲存到Eden空間,一旦Eden空間不足,Eden空間的記憶體回收(gc)將會被觸發。記憶體回收時識別可達的對象並複製這些可達對象到活躍的survivor空間。然後將整個Eden空間視為一個閒置、連續的、可以重新分配的記憶體塊。

在這種情況下的分配過程就像切一塊乳酪一樣。每一塊都會被連續的切下來,然後旁邊被切下來的這些切片就會被“吃掉”,優勢在於分配僅僅只需要指標相加。



為了識別可達的對象就要進行對象圖的檢索。檢索從一組確保可達的“root”對象開始,例如每個線程都有一個root對象。然後搜尋找到root集所指向的對象,然後不停的向外拓展直到找到所有的可達對象。下圖很好的展示了這一過程。



並行回收(parallel scavenge)上下文中的並行(Parallel )所指的是同時運行多個線程來完成記憶體回收。千萬不要和增量式GC(incremental GC)相混淆,即收集器可以和應用程式同時或者交叉運行。並行回收通過更好地使用現代多核CPU來提高總體GC輸送量。並行特性是通過給每個線程一組root標記和對象表的一部分來實現。

有兩個倖存者空間(survivor spaces),但是其中只有一個在任何時候都是處於啟用狀態。它們回收垃圾的方式和eden空間的回收方式一致。主要思想就是當對象從eden空間中升遷(eden空間進行記憶體回收時倖存下來的對象)時這些對象將會被拷貝到活躍的倖存者空間(survivor space)中。然後,當撤銷空間的時候它們就會被拷貝到不活躍的倖存者空間(survivor space)中。一旦活躍的倖存者空間(survivor space)完成撤銷,不活躍的倖存者空間(survivor space)立馬被啟用並且被撤銷的活躍空間變成不活躍。這主要是通過將指標指向倖存者空間(survivor space)的開頭來實現的,並且意味著倖存者空間(survivor space)中的所有不可達對象可以以分配給單個指標為代價而被釋放。

新生代的設計與時間權衡(Young Gen design and time tradeoffs)

因為只是涉及到拷貝可達對象和即時變換指標,所以eden空間和倖存者空間(survivor space)的回收和可達對象的數量成正比。這一點非常重要,因為由於分代假設(generational hypothesis)我們知道大多數的對象在很早的時候就已經不可達,並且沒有GC成本來釋放與之相關的記憶體。

倖存者( survivor spaces)空間的設計構想來源於這樣一種理念:更早的回收比在老年代空間(tenured space)中回收花銷更小。CG運行時對象持續以hemispheric的方式回收可以提高系統整體的輸送量。

最終,eden空間被組織成一個單獨連續的空間,使得對象分配的開銷變得很低。C程式可能會使用“malloc”命令分配記憶體塊,這將會涉及到遍曆一些列閒置記憶體空間嘗試找到足夠大的記憶體塊。當你使用arena allocator並分配你需要的連續空間時,你需要做的就是檢查是否有足夠的空閑空間然後以對象的大小為增量來移動指標。

並行標記和清除(Parallel Mark and Sweep)

經過一定次數的回收之後,倖存下來的對象進入了老年代空間(tenured space)。它們倖存的次數稱為“tenuring threshold(老年代閾值,也稱提升閾值)”,老年代空間的回收工作和eden空間的回收工作有一些不同,它所使用的是一個被稱為標記和清除的演算法(mark and sweep)。每個對象都有一個與之相關聯的標記位。這些標記初始值都被設定為false,在對對象圖進行檢索時,如果對象可達,那可達對象的標記就會被設定成true。

識別可達對象的圖檢索與我們上文對新生代(young generation)的檢索描述類似。不同點在於使用標記取代了可達對象的拷貝。標記完成之後就可以遍曆對象表並釋放不可達對象所佔用的空間。這個過程通過多線程並行完成,每個線程檢索堆中的一個區。

不幸的是這一刪除不可達對象的過程會讓老年代空間(tenured space)看起來像瑞士乳酪(Swiss Cheese)。你得到了一些可以儲存物件的使用過的記憶體,並且這些記憶體空間和過去的一些可達對象所使用的記憶體空間之間形成了空隙。這種記憶體片段對於應用程式的執行效率來說是非常不利的,因為這讓在這些空洞的記憶體空間中分配比它大的對象變得不可能。


Cheese after Mark and Sweep.

為了減少類似於瑞士乳酪(Swiss Cheese)這樣的問題,並行標記/清除(Parallel Mark/Sweep)壓縮了堆以便在老年代空間(tenured space)的開頭分配連續可達的對象。對象刪除之後檢索老年代空間(tenured space)的地區以確定那些地區佔有率低,那些地區佔有率高。佔有率低的地區中的可達對象會被移動到佔有率高的地區。這些操作自然是在上一個壓縮階段的記憶體的底端,在這個階段對象的移動實際上是通過分配給目的地區域的線程去執行,而不是來源區域( source region)。


Low occupancy cheese.

小結

並行回收將堆分為四個空間:eden, 兩個倖存者空間(survivor spaces)、老年代空間(tenured space)。

並行回收使用了並行、拷貝收集器回收Eden和倖存者空間(survivor spaces)。

在老年代空間(tenured space)使用了不同的演算法。該演算法標記了所有的對象,刪除不可達對象然後壓縮空間。

並行回收擁有良好的輸送量,但是當其運行時會暫停整個應用。

原文:https://www.javacodegeeks.com/2013/06/garbage-collection-in-java-2.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.