摘要:垃圾回收器追蹤所有正在使用的對象,將無用對象標(biāo)記為垃圾。自動化指針內(nèi)存回收自動化的最好方式之一是使用鉤子函數(shù)。它們可能因?yàn)槎喾N原因發(fā)生,但是這種垃圾回收器是最主流的一種。
原文出處:What Is Garbage Collection?
一眼就應(yīng)該從名稱看出垃圾回收機(jī)制的含義-查找垃圾,然后丟棄。事實(shí)正好相反。垃圾回收器追蹤所有正在使用的對象,將無用對象標(biāo)記為垃圾。請留意,我們開始研究JVM的“Garbage Collection”的實(shí)現(xiàn)細(xì)節(jié)。
避免倉促進(jìn)入細(xì)節(jié),我們因該從入門開始入手。理解垃圾收集器的一般規(guī)律,核心、概念,處理方法。
鄭重聲明:本文關(guān)注的是Oracle的Hotspot和OpenJDK。其他運(yùn)行環(huán)境或者其他的JVM,諸如jRockit,IBM J9、以及本手冊提及的一些產(chǎn)品會有一些差異化。
內(nèi)存管理指南
在我們開始講解垃圾回收器的工作方式之前,你需要手動為你的數(shù)據(jù)分配一塊可用空間。如果你忘記分配,你將不能重復(fù)使用這塊空間。這塊空間將被聲明但是不能被使用。例如,內(nèi)存泄漏。
下面是一個用C實(shí)現(xiàn)的簡單內(nèi)存管理使用示例:
int send_request() { size_t n = read_size(); int *elements = malloc(n * sizeof(int)); if(read_elements(n, elements) < n) { // elements not freed! return -1; } // … free(elements) return 0; }
正如您看到的,它非常容易忘記去釋放內(nèi)存。內(nèi)存泄漏是一個比現(xiàn)在更加廣泛的共性問題。你只能把內(nèi)嵌在你的代碼來克服這個問題。因此,最好的方法是自動回收不用的內(nèi)存,以完全避免人為錯誤。例如Garbage Collection(GC)自動化操作。
自動化指針
內(nèi)存回收自動化的最好方式之一是使用鉤子函數(shù)。例如,在C++中我們使用vector做同樣的事情,當(dāng)數(shù)據(jù)在作用域不再使用時被自動調(diào)用的一種鉤子函數(shù):
int send_request() { size_t n = read_size(); vectorelements = vector (n); if(read_elements(elements.size(), &elements[0]) < n) { return -1; } return 0; }
但是多數(shù)情況下更加復(fù)雜,特別是對象被多個線程跨線程共享,僅僅使用鉤子函數(shù)不合適,由此產(chǎn)生最簡單的垃圾回收機(jī)制:引用計數(shù)。對于每一個對象,只要簡單知道它被引用了多少次,當(dāng)計數(shù)器歸零的時候,它就被安全回收。下面是C++共享指針的著名例子:
int send_request() { size_t n = read_size(); auto elements = make_shared>(); // read elements store_in_cache(elements); // process elements further return 0; }
現(xiàn)在,為了避免元素在下一時刻被其他函數(shù)調(diào)用,我們也許應(yīng)該將它們緩存起來。在這種情況下,我們不能選擇當(dāng)它出了作用域就銷毀vector。因此,我們使用shared_ptr。它記錄引用次數(shù)。在它的作用域內(nèi)數(shù)量增加,在作用域之外次數(shù)減少。一旦引用次數(shù)歸零,shared_ptr 自動刪除其下的vector。
內(nèi)存自動管理
從上面的C++代碼可以看出,我們依然明確提出關(guān)注內(nèi)存管理。但是如果使用這種方式管理所有的內(nèi)存有會怎樣呢?它變得非常方便,自此開發(fā)人員不再考慮自己手動清除。運(yùn)行環(huán)境會自動識別不再使用的內(nèi)存并且釋放它。換句話說,它自動回收垃圾。世界上第一款垃圾收集于1959年使用Lisp語言實(shí)現(xiàn),自此相關(guān)技術(shù)開始向前發(fā)展。
引用計數(shù)
上文提到我們使用C++共享指針的方式管理所有對象。許多語言,例如 Perl, Python ,PHP都采用這種方式。下圖很好說明了這種方法:
綠色云狀圖標(biāo)指向的對象說明他們?nèi)匀槐怀绦蛘加谩<夹g(shù)上,他們類似于當(dāng)前執(zhí)行方法的本地變量或者靜態(tài)變量或者其他。不同語言之間的差別很大,本文不做關(guān)注。
藍(lán)色圖標(biāo)表示內(nèi)存中存活的對象,里面的數(shù)字代表它們被引用的次數(shù)。最后,灰色圖標(biāo)表示沒有被任何存活對象引用(就是直接被綠色云狀代表對象引用的對象)。灰色對象就這樣被當(dāng)成垃圾,被垃圾收集器清除。
這看起來很不錯,不是嗎?好吧,的確,但是這種方式存在一個巨大的缺點(diǎn)。這些沒有在作用域中對象發(fā)生環(huán)狀引用,由于環(huán)狀引用導(dǎo)致他們的引用計數(shù)不歸零。下面是示意圖:
看到了嗎?實(shí)際上,紅色對象沒有被應(yīng)用程序使用而成為垃圾。由于引用計數(shù)的局限性,他們造成了內(nèi)存泄漏。
有幾種方法客服這種情況,例如使用特殊的“”weak“”引用,或者為了環(huán)狀應(yīng)用特殊的算法。Perl, Python ,PHP使用哪種方式處理,不在本文的討論范圍之內(nèi)。相反,我開始討論更多JVM的實(shí)現(xiàn)細(xì)節(jié)。
標(biāo)記清除
首先,對于可達(dá)對象,JVM有著明確的定義。與上面章節(jié)中綠色云狀圖模糊定義不同的是,我們有一個叫做Garbage Collection Roots(GC Root)的明確定義:
局部變量
活躍線程
靜態(tài)域
JNI引用
JVM使用這種方式追蹤所有可達(dá)(存活)的對象,通過被稱作標(biāo)記清除算法重復(fù)掃描確定不可達(dá)對象。該算法包含兩步:
標(biāo)記,掃描所有的可達(dá)對象,在本地內(nèi)存這些對象的副本。
清除,確保所有被不可達(dá)對象占據(jù)的內(nèi)存空間可以在下一次重新分配。
JVM中多種不同的算法,例如Parallel Scavenge,Parallel Mark+Copy,CMS,他們的實(shí)施階段不盡相同,但是執(zhí)行步驟和上面描述的兩步類似。
這些算法很重要的一點(diǎn)是保證環(huán)形引用不再泄漏:
不太好的一點(diǎn)是,回收操作發(fā)生的時候,所有的應(yīng)用線程被停止。正如它們一直在改變引用導(dǎo)致無法準(zhǔn)確計算它們的應(yīng)用的那樣。像這種應(yīng)用線程被暫時停止,以便JVM活動的晴空稱之為“”stop-the-world“”。它們可能因?yàn)槎喾N原因發(fā)生,但是這種垃圾回收器是最主流的一種。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66334.html
摘要:正好最近在學(xué)習(xí)的各種實(shí)現(xiàn)原理,在這里斗膽翻譯一篇垃圾回收機(jī)制原文鏈接。自動管理的機(jī)制中,通常都會包含垃圾回收機(jī)制。二垃圾回收機(jī)制的概念垃圾回收,是一種自動管理應(yīng)用程序所占內(nèi)存的機(jī)制,簡稱方便起見,本文均采用此簡寫。 最近關(guān)注了一個國外技術(shù)博客RisingStack里面有很多高質(zhì)量,且對新手也很friendly的文章。正好最近在學(xué)習(xí)Node.js的各種實(shí)現(xiàn)原理,在這里斗膽翻譯一篇Node...
摘要:原文出處垃圾回收機(jī)制標(biāo)記清除算法介紹最主要的理論算法之一,在實(shí)踐過程中,為了真實(shí)情景需要,需要許多調(diào)整。因此不會僅僅標(biāo)記清除,垃圾回收期間,內(nèi)存整理進(jìn)程同時在工作。不同內(nèi)存區(qū)域的垃圾收集機(jī)制不辣么容易理解。 原文出處:java垃圾回收機(jī)制 標(biāo)記清除算法介紹最主要的理論算法之一,在實(shí)踐過程中,為了真實(shí)情景需要,需要許多調(diào)整。舉一個簡單例子,我們檢查JVM需要做的各種事情,以便我們安全地去...
摘要:原文出處這種垃圾收集器的官方名稱是。使用收集器的名稱。事件時長記錄不同的類型回收期間垃圾收集器線程消耗事件調(diào)用操作系統(tǒng)活著等待系統(tǒng)事件消耗時間應(yīng)用停頓的時鐘時間?,F(xiàn)在我們看一些一些任務(wù)的時間,垃圾收集器線程等待很長時間。 原文出處:Concurrent Mark and Sweep 這種垃圾收集器的官方名稱是Mostly Concurrent Mark and Sweep Garbag...
摘要:原文出處設(shè)計的一個重要目標(biāo)是設(shè)置階段的持續(xù)時長和頻率,因?yàn)槔占骺深A(yù)測,可配置。收集器盡自己最大努力高概率實(shí)現(xiàn)目標(biāo)但不是必然,它會是硬實(shí)時。因此名稱是收集器。運(yùn)行不同使用獨(dú)立的收集器。 原文出處:G1 – Garbage First G1設(shè)計的一個重要目標(biāo)是設(shè)置stop-the-world階段的持續(xù)時長和頻率,因?yàn)槔占骺深A(yù)測,可配置。事實(shí)上,G1是一款軟實(shí)時的收集器,意味著你...
摘要:本文將會深入分析的引擎的內(nèi)部實(shí)現(xiàn)。該引擎使用在谷歌瀏覽器內(nèi)部。同其他現(xiàn)代引擎如或所做的一樣,通過實(shí)現(xiàn)即時編譯器在執(zhí)行時將代碼編譯成機(jī)器代碼。這可使正常執(zhí)行期間只發(fā)生相當(dāng)短的暫停。 原文 How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code 幾周前我們開始了一個系列博文旨在深入...
閱讀 1790·2021-10-11 10:59
閱讀 2442·2021-09-30 09:53
閱讀 1816·2021-09-22 15:28
閱讀 2825·2019-08-29 15:29
閱讀 1590·2019-08-29 13:53
閱讀 3236·2019-08-29 12:34
閱讀 2887·2019-08-26 10:16
閱讀 2686·2019-08-23 15:16