引用計數法和根搜索算法


如何判斷對象是否存活

引用計數法

概念

  • 引用計數法就是如果一個對象沒有被任何引用指向,則可視之為垃圾。這種方法的缺點就是不能檢測到環的存在。
  • 首先需要聲明,至少主流的Java虛擬機里面都沒有選用引用計數算法來管理內存。 

什么是引用計數算法:

  •  給對象中添加一個引用計數器,每當有一個地方引用它時,計數器值加1;
  • 當引用失效時,計數器值減1.任何時刻計數器值為0的對象就是不可能再被使用的。

那為什么主流的Java虛擬機里面都沒有選用這種算法呢?

其中最主要的原因是它很難解決對象之間相互循環引用的問題。

 

根搜索算法

概念

  • 這個算法的基本思想是通過一系列稱為“GC Roots”的對象作為起始點,從這些節點向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈(即GC Roots到對象不可達)時,則證明此對象是不可用的。

那么問題又來了,如何選取GCRoots對象呢?

在Java語言中,可以作為GCRoots的對象包括下面幾種:

(1). 虛擬機棧(棧幀中的局部變量區,也叫做局部變量表)中引用的對象。

(2). 方法區中的類靜態屬性引用的對象。

(3). 方法區中常量引用的對象。

(4). 本地方法棧中JNI(Native方法)引用的對象。

下面給出一個GCRoots的例子,如下圖,為GCRoots的引用鏈。

 

舉例分析,看下面的圖:

 

 

 

根搜索算法的基本思路就是通過一系列名為”GC Roots”的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引用鏈相連時,則證明此對象是不可用的。

從上圖,reference1、reference2、reference3都是GC Roots,可以看出: 

  1. reference1-> 對象實例1; 
  2. reference2-> 對象實例2; 
  3. reference3-> 對象實例4; 
  4. reference3-> 對象實例4 -> 對象實例6; 

可以得出對象實例1、2、4、6都具有GC Roots可達性,也就是存活對象,不能被GC回收的對象。 
而對於對象實例3、5直接雖然連通,但並沒有任何一個GC Roots與之相連,這便是GC Roots不可達的對象,這就是GC需要回收的垃圾對象。

 

引用計數法 已經被淘汰了!因為循環依賴問題!

A a = new A()    每個對象有個年齡 大於了一定年齡(15) 存放老年代 否則 新生代

GC線程不定時進行回收,如果對象被應用的話,年齡就+1,如果沒有被繼續回收則-1

如果年齡為0的話,被回收

循環依賴問題:

 A a = new A()  

 B b = new B() 

a.x=b

b.x=a

a=null

b=null

很難判斷 然后 怎么去標記為0  去回收

 

根搜索算法  GCRoots 沒有和GCRoots  需要和根節點有依賴關系 如果沒有和GCRoots有任何引用關系情況,GC認為不可達對象。 

 遍歷一遍看看 與GCRoots有引用沒

 

 

只有 user3和user5 不可達 。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM