摘要:原文出處垃圾回收機制標記清除算法介紹最主要的理論算法之一,在實踐過程中,為了真實情景需要,需要許多調整。因此不會僅僅標記清除,垃圾回收期間,內存整理進程同時在工作。不同內存區域的垃圾收集機制不辣么容易理解。
原文出處:java垃圾回收機制
標記清除算法介紹最主要的理論算法之一,在實踐過程中,為了真實情景需要,需要許多調整。舉一個簡單例子,我們檢查JVM需要做的各種事情,以便我們安全地去創建對象。
清除壓縮
當清除期間,JVM必須確保區域被不可達對象填充。這會(終將會)導致內存碎片化,同樣會導致磁盤碎片化,由此產生兩個問題:
寫操作因為尋找下一個足夠尺寸的空間變得耗費時間,這個寫操作不再簡單。
當創建新對象的時候,JVM分配一個連續的空間。如果內存碎片遍布每一個點,沒有足夠的空間容納新創建的對象,分配就會發生錯誤。
為了避免上面的問題,JVM會確保碎片化不會失控。因此不會僅僅標記清除,垃圾回收期間,"內存整理"進程同時在工作。這個進程重新分配所有的可達對象讓他們緊密排列,消除(或者減少)碎片。下面是示意圖:
分代假設
正如我們之前提到,垃圾收集會引起應用徹底停頓。對象越多回收垃圾花費的時間越長,這是顯而易見的。如果我們把使用一小塊內存工作變成可能,那又會怎樣呢?為了研究這種可行性,一些專家發現應用的大多數內存分為以下兩種情況:
絕大多數對象很快就成為無用對象。
很少部分對象講過很長時間存活下來。
上面的觀察結果歸類于新生代假設。基于這個假設:VM內存空間被劃分為Young代 和Old代,后者有時也叫做Tenured。
眾多算法在提升GC性能上已經取得進展,使得擁有這樣一個獨立易清除的內存區域變成現實。
這種方式雖說不上毫無問題。當垃圾收集器收集一個分代中的對象的時候,不同分代中的對象彼此相互引用的時,實際上被當作"GC roots"。
但是更更要的一點是,分代假設并不適用于一些應用。自此,因為那些“夭折”和“有可能永生”的對象,GC算法做了優化,JVM對那些期待更久生命的對象表現得友好。
內存空間
讀者應該了解下圖中java堆區里面的內存劃分。不同內存區域的垃圾收集機制不辣么容易理解。應該注意,不同GC算法實現細節可能不同,然而它們的理念是一致的。
Eden
Eden區是對象被新創建的時候分配的內存區域。在這個區域中,多線程可以同時創建多個對象。在Eden區里,Eden 被分成一個或多個Thread Local Allocation Buffer (縮寫:TLAB)。在這些緩存里,JVM允許線程在對應的緩存中分配絕大多數的對象,避免昂貴的多線程同步。
當TLAB中不能分配空間時(因為空間不足),JVM會移到共享的Eden區去分配,如果共享Eden空間也不足時,Young代中垃圾回收器去釋放更多的空間。如果在GC之后還沒有足夠的空間以供使用,對象會在Old代中分配。
當Eden回收期間,GC把所有的可達對象標記為存活。
我們已經提前注意到,對象可以跨代關聯,因此我們必須有一個快捷途徑去檢查其他代的對象引用Eden區中的對象。
從一開始就記錄所有的分代引用是不可取的, JVM有自己的機制:卡標記。事實上,JVM僅僅標記Eden里面有可能Old代引用Eden代的對象的“臟”對象的位置,你可以在Nitsan的博客里了解更多的信息。
標記階段完成之后,Eden區下面所有存活的對象被復制到Survivor下面的一塊區域中。現在,Eden區被清空,重新分配新建對象。正如“標記-復制”的名稱一樣:存活的對象被標記,然后復制(不是移動)到Survivor區。
Survivor區
緊鄰Eden區的下一個區域時兩個叫做from和to的Survivor區。需要注意的一點,兩塊區域中的一塊是空的。
Survivor中的空的區域會保存下一刻Young代中垃圾回收后的對象。Young代所有存活的對象(包括Eden區和Survior區中非空的from區域)被復制到Survivor區的"to"區域。在這之后,“to”區域存放所有對象,“from”區域清空。兩者進行調換(譯者注:即from變成to,to變成from)。
在兩個區域進行數次復制存活對象操作,直到一些對象足夠成熟(“old enough”)。記住這一點,基于分代假設,一些對象在數次GC之后存活下來,而且在很長一段時間內繼續被引用。
這樣的“tenured”對象會升級到Old代。這種情況發生的時候,對象不再從Survuvor區一個區域移動到另外一個區域,而是進入Old區,在成為不可達對象之前它們一直存在在old區中。
為了確定哪些對象“old enough”,需要為old區提供一種算法,GC記錄幸存對象的詳細信息。每代GC完成之后,那些依然存活的對象年齡進行增長。每當年齡超過設定的閥值之后,對象才會被升遷到old區。
實際上閥值被JVM動態設定,-XX:+MaxTenuringThreshold 除外,它設置最高限定。XX:+MaxTenuringThreshold=0 表示跳過Survivor區的兩個區域之間復制過程直接進入old區。jvm默認閥值是GC循環15次。在Hotspot是最大值。
Survivor區空間不足以容納Young代所有存活對象的時候升遷操作被提前觸發。
Old代
Old代的具體實現細節巨復雜。Old代通常被那些幾乎不可能被當作垃圾的對象占據。
Old代GC觸發的次數比Young代少。因此,Old代中的存活對象,不會發生標記復制過程。相反,這些對象保持最小碎片化。這種算法建立在不同維度之上。大體上,分為以下幾步:
通過設置所有GC roots可達的對象標記位來標記所有可達對象。
刪除所有的不可達對象。
通過復制對象并緊密排列在Old區的頂端壓縮Old區的空間。
正如你看到上面描述的那樣,Old代的GC必須明確處理壓縮錯左避免過多的碎片。
PermGen
JAVA 8之前中被稱作“Permanent Generation”的特殊區域。這是以前存放例如class的metadata。而,Permgen還存儲String之類的額外數據。實際上為JAVA開發者添加了許多麻煩,因為很難預測到底需要多少的空間。這些錯誤的預測結果表現形式為java.lang.OutOfMemoryError: Permgen space。除非是類似OutOfMemoryError的原因是真的是因為內存泄漏,解決這種問題的簡單方法是增加permgen尺寸。下圖中設置permgen尺寸的最大值為256M:
java -XX:MaxPermSize=256m
Metaspace
正如預測metadata是一件紛繁復雜的事情那樣,JAVA 8移除了Permanent區,換作Metaspace。從那時起,絕大多數復雜的事情都被移到Java heap區。
類定義文件,現在都存入叫做“Metaspace”的區域中。他相當于本地內存的一塊區域。理論上,Metaspace尺寸僅僅受限于JAVA進程可獲得本地內存大小。將JAVA開發人員從僅僅在應用多增加一個類就造成java.lang.OutOfMemoryError: Permgen space的困境中解脫出來。需要注意的是這個看起來不受限制沒有損失的空間-讓Metaspace無限制的增長你會引起內存重交換或者/和本地內存分配失敗。
某些場合你希望保護自己,你可以如下圖所示限制Metaspace增長,Metaspace尺寸限制在265M:
java -XX:MaxMetaspaceSize=256m
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66337.html
摘要:正好最近在學習的各種實現原理,在這里斗膽翻譯一篇垃圾回收機制原文鏈接。自動管理的機制中,通常都會包含垃圾回收機制。二垃圾回收機制的概念垃圾回收,是一種自動管理應用程序所占內存的機制,簡稱方便起見,本文均采用此簡寫。 最近關注了一個國外技術博客RisingStack里面有很多高質量,且對新手也很friendly的文章。正好最近在學習Node.js的各種實現原理,在這里斗膽翻譯一篇Node...
摘要:垃圾回收器追蹤所有正在使用的對象,將無用對象標記為垃圾。自動化指針內存回收自動化的最好方式之一是使用鉤子函數。它們可能因為多種原因發生,但是這種垃圾回收器是最主流的一種。 原文出處:What Is Garbage Collection? 一眼就應該從名稱看出垃圾回收機制的含義-查找垃圾,然后丟棄。事實正好相反。垃圾回收器追蹤所有正在使用的對象,將無用對象標記為垃圾。請留意,我們開始研究...
摘要:原文出處這種垃圾收集器的官方名稱是。使用收集器的名稱。事件時長記錄不同的類型回收期間垃圾收集器線程消耗事件調用操作系統活著等待系統事件消耗時間應用停頓的時鐘時間。現在我們看一些一些任務的時間,垃圾收集器線程等待很長時間。 原文出處:Concurrent Mark and Sweep 這種垃圾收集器的官方名稱是Mostly Concurrent Mark and Sweep Garbag...
摘要:本文將會深入分析的引擎的內部實現。該引擎使用在谷歌瀏覽器內部。同其他現代引擎如或所做的一樣,通過實現即時編譯器在執行時將代碼編譯成機器代碼。這可使正常執行期間只發生相當短的暫停。 原文 How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code 幾周前我們開始了一個系列博文旨在深入...
閱讀 1229·2021-11-24 09:39
閱讀 380·2019-08-30 14:12
閱讀 2592·2019-08-30 13:10
閱讀 2434·2019-08-30 12:44
閱讀 958·2019-08-29 16:31
閱讀 845·2019-08-29 13:10
閱讀 2434·2019-08-27 10:57
閱讀 3152·2019-08-26 13:57