1. 程式人生 > >java垃圾回收之 引用計數法

java垃圾回收之 引用計數法

基本概念

  • 在物件中引入計數器(無符號整數),用於記錄有多少物件引用了該物件。
  • 通過增減計數器實現對記憶體的管理。
  • 分配物件時將計數器置1。
  • 更新引用時先對新指定的物件進行計數器加,而後才對舊物件進行減。
  • 在對計數器做減法時,判斷其計數器是否等於0,等於0 表示為垃圾,即可進行回收。
  • 在更新引用時就進行了垃圾的標記與回收,因此STW會很短而且當物件變垃圾時能立馬被回收。

優缺點

優點

  1. 即刻回收垃圾,在更改引用時就知道該物件是否為垃圾若是垃圾立馬進行回收(但是該操作會佔用使用者執行緒的時間片)
  2. STW短,回收垃圾不需要遍歷堆了。
  3. 不需要根據GC root遍歷。

缺點

  1. 計數器值增減頻繁。
  2. 計數器需要佔用很多位。
  3. 實現繁瑣,更新引用時很容易導致記憶體洩露。
  4. 迴圈引用無法回收(最重要的缺點)

改進

延遲引用計數法

針對計數器增減頻繁

  • 從根引用的指標變化不修改計數器,為了使還存在引用的物件被回收,引入ZCT(Zero Count Table)記錄計數器為0的物件(當為0時不直接刪除而是加入到該表中)。
  • 分配塊時,先正常分配(應該也是通過空閒連結串列),如果分配失敗則從ZCT中找可以真正的垃圾物件進行回收與分配。
  • 掃描ZTC表需要遍歷GC root,對所有GC root引用的計數器加1,而後遍歷ZTC,此時計數器為0的即為垃圾,最後對GC root引用物件減一(還原)。

Sticky引用計數法

針對計數器佔用很多位

由於大多數物件的引用並不會很多,可以減少計數器的位寬,當計數器溢位時有兩種處理方式:

  1. 不管,對於溢位的物件不再增減計數器。此時無法判斷是否為垃圾因此不再關此物件,溢位的可能性很低所以是一個可以考慮的解決辦法。
  2. 使用GC標記-清除演算法,先把所有物件(==我覺得處理已溢位的就可以?==)的計數器置0,而後遍歷GC root,可引用的將計數器置1,清除階段則清理那些計數器為0的。

1位引用計數法

Sticky的極端例子

  • 計數器只有1位,0表示只有一個引用(UNIQUE)1表示多引用(MULTIPLE)。
  • 更新引用時通過複製某個指標來更新。

==覺得有問題,怎麼找到可以被複制的指標呢?指標是單鏈表,無法通過物件找到其指標吧==

部分標記-清除演算法

針對迴圈引用

  • 為了解決迴圈引用不能被回收有采用在某些時候加入GC標記-清除演算法,然而迴圈引用往往很少,效率很低。
  • 該方法是隻對可能存在迴圈引用的物件群進行Sweep。
  • 物件被標記為四種顏色,黑:不是垃圾,白:垃圾,灰:搜尋過的物件,陰影:可能是迴圈引用物件。上色採用兩位標記
  • 當刪除引用關係時,先自減,而後如果計數器為0則回收該物件,否則將該物件置為陰影並加入到hatch_queue
  • 當空閒連結串列無法分配時將去hatch_queue中掃描是否存在迴圈垃圾可進行回收。
  • 遍歷取hatch_queue中物件分別做paint_gray、scan_gray和collect_white
  • paint_gray將物件置灰,而後將所有子物件計數器減1,並呼叫迭代paint_gray.
  • scan_gray將灰色中計數器為0的物件置白,大於0的塗成黑色。
  • collect_white回收白色物件

相關推薦

java垃圾回收 引用計數

基本概念在物件中引入計數器(無符號整數),用於記錄有多少物件引用了該物件。通過增減計數器實現對記憶體的管理。分配物件時將計數器置1。更新引用時先對新指定的物件進行計數器加,而後才對舊物件進行減。在對計數

【知識點】垃圾回收引用計數迴圈引用

引用計數常用來說明垃圾收集的工作方式,但似乎從未被應用與任何一種Java虛擬機器中實現。《java程式設計思想》 關於引用計數法,我們可以先看一段wiki上的描述: As a collection algorithm, referenc

java 垃圾回收標記算

執行 是否 本地方法棧 虛擬 垃圾回收機制 垃圾回收 main nbsp 循環引用 對象被判定為垃圾的標準 1、沒有被其他對象引用 判定對象是否為垃圾的算法 1、引用計數算法(不是主流垃圾回收機制)   1.1 判定對象的引用數量     1.1.1 通過判

python垃圾回收機制:引用計數 VS js垃圾回收機制:標記清除

js垃圾回收機制:標記清除 Js具有自動垃圾回收機制。垃圾收集器會按照固定的時間間隔週期性的執行。 JS中最常見的垃圾回收方式是標記清除。 工作原理 當變數進入環境時,將這個變數標記為“進入環境”。當變數離開環境時,則將其標記為“離開環境”。標記“離開環境”的就回收記憶體。 工作流程 1. 

java 物件存活分析——引用計數&可達性分析

java虛擬機器總共分為五個區域,其中三個是執行緒私有:程式計數器,虛擬機器棧,本地方法棧,兩個是執行緒共享:堆,方法區。執行緒私有的區域等到執行緒結束時(棧幀出棧時)會自動被釋放,空間比較容易清理。而執行緒共享的java堆和方法區中的空間較大而且沒有執行緒的回

java垃圾回收Minor GC和Major GC

最近在讀周志明寫的 深入理解Java虛擬機器:JVM高階特性與最佳實踐 對Minor GC和Major GC做點筆記  新生代 GC(Minor GC):指發生在新生代的垃圾收集動作,因為 Java 物件大多都具 備朝生夕滅的特性,所以 Minor GC 非常頻繁

java垃圾回收複製演算法

之前的java垃圾回收演算法之-標記清除 會導致記憶體碎片。下文的介紹的coping演算法可以解決記憶體碎片問題。概述如果jvm使用了coping演算法,一開始就會將可用記憶體分為兩塊,from域和to域, 每次只是使用from域,to域則空閒著。當from域記憶體不夠了,開

垃圾回收——判斷物件是否存活演算法-引用計數詳解

垃圾回收首要的任務就是確定哪些物件是垃圾,哪些物件可進行回收,上節課我們也說過了,判定物件為垃圾物件的兩種演算法,一種是引用計數法,另一種是可達性分析法,我們本節課就來詳細的瞭解一下什麼是引用計數法。 引用計數法的思路是,在物件中新增一個引用計數器,當有地方引用這個物件的時候,這個引用計數器的值

深入理解JVM學習筆記(十九、JVM 垃圾回收機制---如何判斷物件是否為垃圾引用計數】)

一、引用計數法         引用計數演算法作為垃圾收集器最早的演算法,有其優勢,也有其劣勢,雖然現在的JVM都不再採用引用計數演算法進行垃圾回收【例如Sun的Java hotspot採用了火車演算法進行垃圾回收】,但這種演算法也並未被淘汰,在著名的單程序高併發快取Red

java垃圾回收演算法-引用計數器

引用計數器演算法算是一種古老的java垃圾回收演算法,目前很多版本的java已經廢棄掉這種演算法了。不過多瞭解歷史解決方案也是很有好處的,通過總結它的優缺點,再與新演算法比較,可以幫助更好的理解新演算法。 引用計數器演算法描述 定義:給每個物件分配一個計

JVM中垃圾回收機制如何判斷是否死亡?詳解引用計數和可達性分析 !

> 因為熱愛,所以堅持。 > 文章下方有本文參考電子書和視訊的**下載地址**哦~ 這節我們主要講垃圾收集的一些基本概念,先了解垃圾收集是什麼、然後觸發條件是什麼、最後虛擬機器如何判斷物件是否死亡。 ### 一、前言   我們都知道Java和C++有一個非常大的區別就是Java有自動的垃圾回收

Java垃圾回收

分代 清理 java 利用 效果 大小 ava 大量 思想 1.標記-清除算法 概念 標記階段:先通過根節點,標記所有從根節點開始的可達對象,因此,未被標記的對象就是未被引用的垃圾對象; 清除階段:清除所有未被標記的對象。 缺點: 標記和清除的過程效率不高(標記和清除都需要

垃圾回收倒置復制

空間 htm div class tar lan 額外 位置 兩種 剛才瀏覽了這篇文章,http://www.importnew.com/26821.html,了解了垃圾回收的一些方法。 我發現其中的復制法有非常聰明的地方,就是能方便的重新排序,為了不再需要對空間進行劃分,

深入理解java垃圾回收

信息 pan 一半 rms err 必須 輪換 找到 兩個 Java虛擬機的內存區域中,程序計數器、虛擬機棧和本地方法棧三個區域是線程私有的,隨線程生而生,隨線程滅而滅;棧中的棧幀隨著方法的進入和退出而進行入棧和出棧操作,每個棧幀中分配多少內存基本上是在類結構確定下來時就已

java垃圾回收Garbage Collection(一、垃圾收集算)

按順序 算法 根據 垃圾收集 無法 虛擬機 mar none 內存空間   垃圾收集算法 標記-清除算法     最基礎的算法是標記-清除(Mark-Sweep)算法。分為標記和清除兩個階段:首先標記出所有需要回收的對象,標記完成後統一回收所有被標記的對象。之所以說是最

Java虛擬機器判斷物件存活的兩種方案:引用計數與可達性分析演算法

java堆和方法區主要存放各種型別的物件(方法區中也儲存一些靜態變數和全域性常量等資訊),那麼我們在使用GC對其進行回收的時候首先要考慮的就是如何判斷一個物件是否應該被回收。也就是要判斷一個物件是否還有其他的引用或關聯使得這個物件處於存活的狀態。我們需要將不在存活狀態的所有物

垃圾回收判斷物件否需要被回收(根搜尋演算法和引用搜索演算法)

根搜尋演算法(JAVA的虛擬機器用的是這個) 可以參考這個 http://blog.csdn.net/qq_15022971/article/details/79162126 引用搜索演算法:是常被初學JAVA者誤解,java的垃圾回收在判斷一個物件是否為可以被回收的物件時,常被誤以為

jvmjava垃圾回收機制詳解

      傳統的C/C++等程式語言,需要程式設計師負責回收已經分配出去的記憶體。顯示進行垃圾回收是一件令人頭疼的事情,因為程式設計師並不總是知道記憶體應該何時進行釋放。如果一些分配出去的記憶體不能及時的回收就會引起系統執行速度下降,甚至導致程式癱瘓,這種現象稱為記憶體洩露

Python垃圾回收迴圈引用

什麼情況存在記憶體洩露 python引用計數 + 分代收集和標記清除(處理迴圈引用),進行垃圾回收,但如下兩種情況依舊存在記憶體洩露: 第一是物件被另一個生命週期特別長(如全域性變數)的物件所引用 第二是迴圈引用中的物件定義了__del__函式,簡而言之,迴

java垃圾回收演算法-標記清除

java垃圾回收演算法之-引用計數器,這個演算法其中一個優點便是,實時性,只要物件的引用計數器的值為0,則立刻回收。接下來介紹的標記清除演算法,當物件的引用計數器的值為0時,不會立刻被回收的。 概念介紹 root物件 在標記清除演算法中,會把如