溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

GC算法與四種引用有哪些

發(fā)布時間:2021-10-12 14:43:25 來源:億速云 閱讀:167 作者:iii 欄目:編程語言

本篇內容介紹了“GC算法與四種引用有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

GC算法

常見的GC算法包括:

  • 引用計數(shù)法

  • 標記清除法

  • 復制算法

  • 標記壓縮法

  • 分代算法

  • 分區(qū)算法

 引用計數(shù)法

實現(xiàn)原理:

  • 對于一個對象A

  • 只要有任何一個對象引用A,A的引用計數(shù)器就加1

  • 引用失效時,引用計數(shù)器就減1

  • 只要對象A的引用計數(shù)器的值為0,對象A就不會再被使用,等待被回收

缺點:

  • 無法處理循環(huán)引用,比如A引用B,B引用A,但是并沒有其他對象引用兩者,此時A和B的引用計數(shù)都不為0,這樣就無法被回收

  • 引用計數(shù)器要求每次引用產生和消除的時候,伴隨一個加法操作和一個減法操作,對系統(tǒng)性能會有一定的影響

由于引用計數(shù)法上述的缺點,Java中并未采用作為GC算法。

 標記清除法

標記清除法將垃圾回收分為兩個階段:

  • 標記階段:通過根節(jié)點標記所有從根節(jié)點開始的可達對象,未被標記的就是垃圾對象

  • 清除階段:清除所有未被標記的對象

標記階段:

GC算法與四種引用有哪些

清除后:

GC算法與四種引用有哪些

缺點很明顯,就是回收后的空間是不連續(xù)的,工作效率會低于連續(xù)的內存空間。

 復制算法

核心思想:

  • 內存空間分為相等的兩塊

  • 每次只使用其中一塊

  • 回收的時候將存活對象移到另一塊中,然后清除正在使用的內存塊中所有對象

  • 交換兩個內存塊的角色

優(yōu)點是回收后的內存空間是沒有碎片的,而缺點是如果存在大量的對象,需要花費大量的時間復制,并且內存只有原來的一半。

比如下圖中的A、B兩塊相同的內存空間,A在垃圾回收的時候,將存活對象復制到B中,B在復制后保持連續(xù):

GC算法與四種引用有哪些

復制完成后,A會被清空,并將B設置為當前使用的空間。

Java的新生代串行垃圾回收器中,使用了復制算法,新生代分為eden區(qū)、from區(qū)以及to區(qū)。其中fromto區(qū)是兩塊內存相同的空間,也叫survivor區(qū),也就是幸存者空間。在垃圾回收的時候,eden區(qū)以及from區(qū)存活的對象會被復制到to區(qū),然后清空from區(qū)與eden區(qū),接著fromto區(qū)的角色將會交換,也就是下一次垃圾回收的時候,會從原來的to區(qū)(新的from區(qū))復制到原來的from區(qū)(新的to區(qū))。

 標記壓縮法

標記壓縮法是一種老年代算法,在標記清除法的基礎上做了一些優(yōu)化,和標記清除法一樣,首先也需要從根節(jié)點開始,對所有可達對象做一次標記,然后將所有存活對象壓縮到內存的一端,接著清理邊界外的所有空間,圖示如下:

GC算法與四種引用有哪些

標記壓縮法的優(yōu)點是可以避免碎片的產生,又不需要兩塊相同的內存空間。

 分代算法

分代算法并不是一種具體的垃圾回收算法,分代算法其實是一種根據(jù)每塊內存空間的特點使用不同回收算法以提高效率的算法。比如:

  • 在新生代中:會有大量的新建對象很快被回收,因此新生代比較適合使用復制算法

  • 在老年代中:采用標記壓縮法或標記清除法

 分區(qū)算法

分區(qū)算法將整個堆空間劃分成連續(xù)的不同小區(qū)間,每個小區(qū)間都獨立使用,獨立回收,如圖所示:

GC算法與四種引用有哪些3 四種引用

Java里面提供了4個級別的引用:

  • 強引用

  • 軟引用

  • 弱引用

  • 虛引用

下面分別來看一下。

 強引用

強引用就是代碼中一般使用的引用類型,強引用的對象是可觸及的,不會被回收,比如:

StringBuffer str = new StringBuffer("a");

如果上面的代碼運行在方法體內,那么局部變量str會被分配在棧上,而對象StringBuffer實例會被分配在堆上,str指向的是StringBuffer實例所在的堆空間,通過str可以操作該實例,str就是StringBuffer實例的強引用。

又比如執(zhí)行了以下代碼:

StringBuffer str1 = str;

那么str1也會指向str指向的對象,也就是它們都指向同一個StringBuffer實例,此時str1==str的值為真,因為兩個指向的是同一個堆空間地址。

強引用的特點如下:

  • 可以直接訪問目標對象

  • 強引用指向的對象不會被系統(tǒng)回收,JVM寧愿拋出OOM也不會回收強引用指向的對象

  • 強引用可能會導致內存泄漏

 軟引用

軟引用是被強引用弱一點的引用類型,如果一個對象只持有軟引用,那么當堆空間不足的時候,就會被回收,軟引用可以使用SoftReference類實現(xiàn),比如下面的代碼:

public static void main(String[] args){
    Byte[] b = new Byte[1024*1024*8];
    SoftReference<Byte[]> softReference = new SoftReference<>(b);
    b = null;
    System.out.println(softReference.get());
    System.gc();
    System.out.println("After GC");
    System.out.println(softReference.get());
    b = new Byte[1024*1024*8];
    System.gc();
    System.out.println(softReference.get());
}

OpenJDK 11.0.10上,加上-Xmx40m的輸出如下:

[Ljava.lang.Byte;@1fbc7afb
After GC
[Ljava.lang.Byte;@1fbc7afb
null

可以看到,當垃圾回收的時候,未必會回收軟引用對象,但當內存緊張時,會回收軟引用對象。

 弱引用

弱引用是比軟引用弱的引用類型,在垃圾回收的時候,只要發(fā)現(xiàn)弱引用,不管系統(tǒng)空間使用情況如何,都會將對象進行回收。但是由于垃圾回收器的線程通常優(yōu)先級不高,并不一定能很快發(fā)現(xiàn)弱引用對象,這種情況下弱引用對象可以存在較長時間。弱引用例子如下:

public static void main(String[] args){
    Byte[] b = new Byte[1024*1024*8];
    WeakReference<Byte[]> softReference = new WeakReference<>(b);
    b = null;
    System.out.println(softReference.get());
    System.gc();
    System.out.println("After GC");
    System.out.println(softReference.get());
}

輸出(-Xmx40m):

[Ljava.lang.Byte;@1fbc7afb
After GC
null

可以看到在GC后,弱引用對象會被立即回收。

軟引用、弱引用的一個常見使用場景是保存可有可無的緩存數(shù)據(jù),當系統(tǒng)內存不足時,這些內存數(shù)據(jù)會被回收,不會導致OOM,而內存充足時,這些緩存數(shù)據(jù)又可以存在相當長的時間,從而起到讓系統(tǒng)加速的作用。

 虛引用

虛引用是所有引用類型中最弱的一個,一個持有虛引用的對象和沒有引用幾乎是一樣的,隨時都可能被垃圾回收器回收。另外,試圖使用虛引用的get()方法獲取強引用的時候,總是會失敗,并且虛引用需要和引用隊列一起使用,作用在與跟蹤垃圾回收過程。

public static void main(String[] args) throws Exception {
    ReferenceQueue<String> queue = new ReferenceQueue<>();
    PhantomReference<String> reference = new PhantomReference<>(new String("test"),queue);
    System.out.println(reference.get());
}

輸出結果:

null

“GC算法與四種引用有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI