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