摘要:根搜索算法它的處理方式就是,設(shè)立若干種根對(duì)象,當(dāng)任何一個(gè)根對(duì)象到某一個(gè)對(duì)象均不可達(dá)時(shí),則認(rèn)為這個(gè)對(duì)象是可以被回收的。
引用計(jì)數(shù)算法
給對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器值就加1;當(dāng)引用失效時(shí),計(jì)數(shù)器值就減1;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的。
缺點(diǎn):引用和去引用伴隨加法和減法,影響性能。
致命的缺陷:對(duì)于循環(huán)引用的對(duì)象無(wú)法進(jìn)行回收。
它的處理方式就是,設(shè)立若干種根對(duì)象,當(dāng)任何一個(gè)根對(duì)象到某一個(gè)對(duì)象均不可達(dá)時(shí),則認(rèn)為這個(gè)對(duì)象是可以被回收的。
可達(dá)性分析:從根(GC Roots)的對(duì)象作為起始點(diǎn),開(kāi)始向下搜索,搜索所走過(guò)的路徑稱為“引用鏈”,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連(用圖論的概念來(lái)講,就是從GC Roots到這個(gè)對(duì)象不可達(dá))時(shí),則證明此對(duì)象是不可用的。
在JAVA語(yǔ)言中,可以當(dāng)做GC roots(GC根)的對(duì)象有以下幾種:
棧(棧幀中的本地變量表)中引用的對(duì)象。
方法區(qū)中的靜態(tài)成員。
方法區(qū)中的常量引用的對(duì)象(全局變量)。
本地方法棧中JNI(一般說(shuō)的Native方法)引用的對(duì)象。
第一和第四種都是指的方法的本地變量表,第二種表達(dá)的意思比較清晰,第三種主要指的是聲明為final的常量值。
標(biāo)記清除算法當(dāng)堆中的有效內(nèi)存空間(available memory)被耗盡的時(shí)候,就會(huì)停止整個(gè)程序(也被成為stop the world),然后進(jìn)行兩項(xiàng)工作,第一項(xiàng)則是標(biāo)記,第二項(xiàng)則是清除。
標(biāo)記:標(biāo)記的過(guò)程其實(shí)就是,遍歷所有的GC Roots,然后將所有GC Roots可達(dá)的對(duì)象標(biāo)記為存活的對(duì)象。
清除:清除的過(guò)程將遍歷堆中所有的對(duì)象,將沒(méi)有標(biāo)記的對(duì)象全部清除掉。
沒(méi)有被標(biāo)記的對(duì)象將會(huì)回收清除掉,而被標(biāo)記的對(duì)象將會(huì)留下,并且會(huì)將標(biāo)記位重新歸0
標(biāo)記-清除算法的缺點(diǎn):
首先,它的缺點(diǎn)就是效率比較低(遞歸與全堆對(duì)象遍歷),導(dǎo)致stop the world的時(shí)間比較長(zhǎng),尤其對(duì)于交互式的應(yīng)用程序來(lái)說(shuō)簡(jiǎn)直是無(wú)法接受。
第二點(diǎn)主要的缺點(diǎn),則是這種方式清理出來(lái)的空閑內(nèi)存是不連續(xù)的,這點(diǎn)不難理解,我們的死亡對(duì)象都是隨即的出現(xiàn)在內(nèi)存的各個(gè)角落的,現(xiàn)在把它們清除之后,內(nèi)存的布局自然會(huì)亂七八糟。而為了應(yīng)付這一點(diǎn),JVM就不得不維持一個(gè)內(nèi)存的空閑列表,這又是一種開(kāi)銷。而且在分配數(shù)組對(duì)象的時(shí)候,尋找連續(xù)的內(nèi)存空間會(huì)不太好找。
復(fù)制算法:(新生代的GC)將原有的內(nèi)存空間分為兩塊,每次只使用其中一塊,在垃圾回收時(shí),將正在使用的內(nèi)存中的存活對(duì)象復(fù)制到未使用的內(nèi)存塊中,之后,清除正在使用的內(nèi)存塊中的所有對(duì)象,交換兩個(gè)內(nèi)存的角色,完成垃圾回收。
將內(nèi)存分為一塊比較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor。當(dāng)回收時(shí),將Eden和Survivor中還存活著的對(duì)象一次性地復(fù)制到另外一塊Survivor空間上,最后清理掉Eden和剛才用過(guò)的Survivor空間。
當(dāng)Survivor空間不夠用時(shí),需要依賴于老年代進(jìn)行分配擔(dān)保,所以大對(duì)象直接進(jìn)入老年代
標(biāo)記-整理算法:(老年代的GC)和標(biāo)記-清除算法一樣,標(biāo)記-壓縮算法也首先需要從根節(jié)點(diǎn)開(kāi)始,對(duì)所有可達(dá)對(duì)象做一次標(biāo)記;但之后,它并不簡(jiǎn)單的清理未標(biāo)記的對(duì)象,而是將所有的存活對(duì)象壓縮到內(nèi)存的一端;之后,清理邊界外所有的空間。
標(biāo)記:它的第一個(gè)階段與標(biāo)記/清除算法是一模一樣的,均是遍歷GC Roots,然后將存活的對(duì)象標(biāo)記。
整理:移動(dòng)所有存活的對(duì)象,且按照內(nèi)存地址次序依次排列,然后將末端內(nèi)存地址以后的內(nèi)存全部回收。因此,第二階段才稱為整理階段。
標(biāo)記-清除算法、復(fù)制算法、標(biāo)記整理算法的總結(jié):三個(gè)算法都基于根搜索算法去判斷一個(gè)對(duì)象是否應(yīng)該被回收,而支撐根搜索算法可以正常工作的理論依據(jù),就是語(yǔ)法中變量作用域的相關(guān)內(nèi)容。因此,要想防止內(nèi)存泄露,最根本的辦法就是掌握好變量作用域,而不應(yīng)該使用C/C++式內(nèi)存管理方式。
在GC線程開(kāi)啟時(shí),或者說(shuō)GC過(guò)程開(kāi)始時(shí),它們都要暫停應(yīng)用程序(stop the world)。
它們的區(qū)別如下:(>表示前者要優(yōu)于后者,=表示兩者效果一樣)
效率:復(fù)制算法>標(biāo)記/整理算法>標(biāo)記/清除算法(此處的效率只是簡(jiǎn)單的對(duì)比時(shí)間復(fù)雜度,實(shí)際情況不一定如此)。
內(nèi)存整齊度:復(fù)制算法=標(biāo)記/整理算法>標(biāo)記/清除算法。
內(nèi)存利用率:標(biāo)記/整理算法=標(biāo)記/清除算法>復(fù)制算法。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/70075.html
摘要:本文詳細(xì)描述了堆內(nèi)存模型,垃圾回收算法以及處理內(nèi)存泄露的最佳方案,并輔之以圖表,希望能對(duì)理解內(nèi)存結(jié)構(gòu)有所幫助。該區(qū)域也稱為內(nèi)存模型的本地區(qū)。在中,內(nèi)存泄露是指對(duì)象已不再使用,但垃圾回收未能將他們視做不使用對(duì)象予以回收。 本文詳細(xì)描述了 Java 堆內(nèi)存模型,垃圾回收算法以及處理內(nèi)存泄露的最佳方案,并輔之以圖表,希望能對(duì)理解 Java 內(nèi)存結(jié)構(gòu)有所幫助。原文作者 Sumith Puri,...
摘要:本人使用的是,以下涉及的默認(rèn)值均以該版本為準(zhǔn)。其中,新生代被細(xì)分為和兩個(gè)區(qū)域,這兩個(gè)區(qū)域分別被命名為和,以示區(qū)分。其中新生帶存放新生的對(duì)象或者年齡不大的對(duì)象,老年代則存放老年對(duì)象。 什么是垃圾回收機(jī)制 不定時(shí)去堆內(nèi)存中清理不可達(dá)對(duì)象。不可達(dá)的對(duì)象并不會(huì)馬上就會(huì)直接回收, 垃圾收集器在一個(gè)Java程序中的執(zhí)行是自動(dòng)的,不能強(qiáng)制執(zhí)行,即使程序員能明確地判斷出有一塊內(nèi)存已經(jīng)無(wú)用了,是應(yīng)該回收...
摘要:直接對(duì)棧的操作只有兩個(gè),就是對(duì)棧幀的壓棧和出棧。中將永久代移除,同時(shí)增加元數(shù)據(jù)區(qū)。在中,本地方法棧和虛擬機(jī)棧是在同一塊兒區(qū)域,這完全取決于技術(shù)實(shí)現(xiàn)的決定,并未在規(guī)范中強(qiáng)制。 原文:https://github.com/linsheng97... 描述一下 JVM 的內(nèi)存區(qū)域 程序計(jì)數(shù)?(PC,Program Counter Register)。在 JVM 規(guī)范中,每個(gè)線程都有它自己的...
摘要:在這種消耗很高的狀態(tài)下,應(yīng)用程序所有的線程都會(huì)掛起,暫停一切正常的工作,等待垃圾回收的完成。但是,因?yàn)榫€程切換和上下文轉(zhuǎn)換的消耗,會(huì)使得垃圾回收的總體成本上升,造成系統(tǒng)吞吐量的下降。 Java 垃圾回收(GC) 泛讀 文章地址: https://segmentfault.com/a/1190000008922319 0. 序言 帶著問(wèn)題去看待 垃圾回收(GC) 會(huì)比較好,一般來(lái)說(shuō)主要的...
閱讀 3022·2021-10-27 14:15
閱讀 3014·2021-09-07 10:18
閱讀 1332·2019-08-30 15:53
閱讀 1584·2019-08-26 18:18
閱讀 3385·2019-08-26 12:15
閱讀 3468·2019-08-26 10:43
閱讀 662·2019-08-23 16:43
閱讀 2218·2019-08-23 15:27