日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java强引用、软引用、弱引用、虚引用-Java的引用类型总共有四种,你都知道吗

發布時間:2025/3/19 java 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java强引用、软引用、弱引用、虚引用-Java的引用类型总共有四种,你都知道吗 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

談引用

強引用(Strong Reference)——不回收

強引用例子

軟引用(Soft?Reference)——內存不足即回收

弱引用(Weak?Reference)——發現即回收

面試題:你開發中使用過WeakHashMap嗎?

虛引用(Phantom?Reference)——對象回收跟蹤

終結器引用(Final?reference)


談引用

1.我們希望能描述這樣一類對象:當內存空間還足夠時,則能保留在內存中;如果內存空間在進行垃圾收集后還是很緊張,則可以拋棄這些對象。

2.【既偏門又非常高頻的面試題】強引用、軟引用、弱引用、虛引用有什么區別?具體使用場景是什么?

3.在JDK1.2版之后,Java對引用的概念進行了擴充,將引用分為強引用(Strong?Reference)、軟引用(Soft?Reference)、弱引用(Weak?Reference)和虛引用(Phantom?Reference)4種,這4種引用強度依次逐漸減弱。

4.除強引用外,其他3種引用均可以在java.lang.ref包中找到它們的身影。如下圖,顯示了這三種引用類型對應的類,開發人員可以在應用程序中直接使用它們。

5.Reference子類中只有終結器引用是包內可見的,其他3種引用類型均為public,可以在應用程序中直接使用。

?? ?強引用(StrongReference):最傳統的“引用”的定義,是指在程序代碼之中普遍存在的引用賦值,即類似“Object?obj =?new Object()”這種引用關系。無論任何情況下,只要強引用關系還存在,垃圾收集器就永遠不會回收掉被引用的對象。

? ? 軟引用(SoftReference):在系統將要發生內存溢出之前,將會把這些對象列入回收范圍之中進行第二次回收。如果這次回收還沒有足夠的內存,才會拋出內存溢出異常。

? ? 弱引用(WeakReference):被弱引用關聯的對象只能生存到下一次垃圾收集之前。當垃圾收集器工作時,無論內存空間是否足夠,都會回收掉被弱引用關聯的對象。

? ? 虛引用(PhantomReference):一個對象是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來獲得一個對象的實例。為一個對象設置虛引用關聯的唯一目的就是能在這個對象被收集器回收時收到一個系統通知。

強引用(Strong Reference)——不回收

1.在java程序中,最常見的引用類型是強引用(普通系統99%以上都是強引用),也就是我們最常見的普通對象引用,也是默認的引用類型

2.當在Java語言中使用new操作符創建一個新的對象,并將其賦值給一個變量的時候,這個變量就成為指向該對象的一個強引用。

3.強引用的對象是可觸及的,垃圾收集器就永遠不會回收掉被引用的對象

4.對于一個普通的對象,如果沒有其他的引用關系,只要超過了引用的作用域或者顯式地將相應(強)引用賦值為null,就是可以當做垃圾被收集了,當然具體回收時機還是要看垃圾收集策略。

5.相對的,軟引用、弱引用和虛引用的對象是軟可觸及、弱可觸及和虛可觸及的,在一定條件下,都是可以被回收的。所以,強引用是造成Java內存泄漏的主要原因之一

強引用例子

StringBuffer str = new StringBuffer("Hello world");

局部變量str指向StringBuffer實例所在堆空間,通過str可以操作該實例,那么str就是StringBuffer實例的強引用。

對應內存結構:

?

此時,如果再運行一個賦值語句:

StringBuffer?str1 =?str;

此時對應的內存結構:

?

強引用只要還有引用,就不會被回收

本例中的兩個引用,都是強引用,強引用具備以下特點:

1.強引用可以直接訪問目標對象。

2.強引用所指向的對象在任何時候都不會被系統回收,虛擬機寧愿拋出OOM異常,也不會回收強引用所指向對象。

3.強引用可能導致內存泄漏。

軟引用(Soft?Reference)——內存不足即回收

1.軟引用是用來描述一些還有用,但非必須的對象。只被軟引用關聯著的對象,在系統將要發生內存溢出異常前,會把這些對象列進回收范圍之中進行第二次回收,如果這次回收還沒有足夠的內存,才會拋出內存溢出異常

2.軟引用通常用來實現內存敏感的緩存。比如:高速緩存就有用到軟引用。如果還有空閑內存,就可以暫時保留緩存,當內存不足時清理掉,這樣就保證了使用緩存的同時,不會耗盡內存。

3.垃圾回收器在某個時刻決定回收軟可達的對象的時候,會清理軟引用,并可選地把引用存放到一個引用隊列(Reference?Queue)。

4.類似弱引用,只不過Java虛擬機會盡量讓軟引用的存活時間長一些,迫不得已才清理。

在JDK1.2版本之后提供了java.lang.ref.SoftReference類來實現軟引用。

Object obj = new Object(); // 聲明強引用 SoftReference<Object> sf = new SoftReference<Object>(obj); // 軟引用 obj = null; // 銷毀強引用

實例:

import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.List;public class Tess {public static class User {public Integer id;public String name;public User(Integer id, String name) {this.id = id;this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}}public static void main(String[] args) {// 創建對象,建立軟引用SoftReference<User> userSoftReference = new SoftReference<User>(new User(1, "zhangsan"));// 從軟引用中重新獲得強引用對象System.out.println(userSoftReference.get());System.gc();System.out.println("After GC:");// 垃圾回收之后獲得軟引用中的對象System.out.println(userSoftReference.get()); // 由于堆內存足夠,不會回收軟引用對象// 讓系統認為內存緊張(內存不夠時,會先進行GC)try {List list = new ArrayList();for (int i = 0; i < 100; i++) {byte[] b = new byte[1024 * 1024 * 600];list.add(b);}} catch (Exception e){e.printStackTrace();} finally {System.out.println(userSoftReference.get()); // 內存緊張,垃圾回收會將軟引用也回收,為null}} }

?

弱引用(Weak?Reference)——發現即回收

1.弱引用也是用來描述那些非必需對象,只被弱引用關聯的對象只能生存到下一次垃圾收集發生為止。在系統GC時,只要發現弱引用,不管系統堆空間使用是否充足,都會回收掉只被弱引用關聯的對象。

2.但是,由于垃圾回收器的線程通常優先級很低,因此,并不一定能很快地發現持有弱引用的對象。在這種情況下,弱引用對象可以存在較長的時間

3.弱引用和軟引用一樣,在構造弱引用時,也可以指定一個引用隊列,當弱引用對象被回收時,就會加入指定的引用隊列,通過這個隊列可以跟蹤?對象的回收情況。

4.軟引用、弱引用都非常適合來保存那些可有可無的緩存數據。如果這么做,當系統內存不足時,這些緩存數據會被回收,不會導致內存溢出。而當內存資源充足時,這些緩存數據又可以存在相當長的時間,從而起到加速系統的作用。

在JDK1.2版之后提供了java.lang.ref.WeakReference類來實現弱引用。

Object obj = new Object(); // 聲明強引用 WeakReference<Object> wr = new WeakReference<Object>(obj); // 聲明弱引用 obj = null; // 銷毀強引用

弱引用對象與軟引用對象的最大不同就在于,當GC在進行回收時,需要通過算法檢查是否回收軟引用對象,而對于弱引用對象,GC總是進行回收。弱引用對象更容易、更快被GC回收

import java.lang.ref.WeakReference;public class Tess {public static class User {public Integer id;public String name;public User(Integer id, String name) {this.id = id;this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}}public static void main(String[] args) {// 創建對象,建立軟引用WeakReference<User> userWeakReference = new WeakReference<User>(new User(1, "zhangsan"));// 從軟引用中重新獲得強引用對象System.out.println(userWeakReference.get());System.gc();System.out.println("After GC:");// 垃圾回收之后獲得弱引用中的對象System.out.println(userWeakReference.get()); // null} }

面試題:你開發中使用過WeakHashMap嗎?

(緩存的Map)

虛引用(Phantom?Reference)——對象回收跟蹤

1.也稱為“幽靈引用”或者“幻影引用”,是所有引用類型中最弱的一個。

2.一個對象是否有虛引用的存在,完全不會決定對象的生命周期。如果一個對象僅持有虛引用,那么它和沒有引用幾乎是一樣的,隨時都可能被垃圾回收器回收。

3.它不能單獨使用,也無法通過虛引用來獲取被引用的對象。當試圖通過虛引用的get()方法取得對象時,總是null。

4.為一個對象設置虛引用關聯的唯一目的在于跟蹤垃圾回收過程。比如:能在這個對象被回收時收到一個系統通知

5.虛引用必須和引用隊列一起使用。虛引用在創建時必須提供一個引用隊列作為參數。當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象后,將這個虛引用加入引用隊列,以通知應用程序對象的回收情況。

6.由于虛引用可以跟蹤對象的回收時間,因此,也可以將一些資源釋放操作放置在虛引用中執行和記錄

7.JDK1.2版本之后提供了PhantomReference類來實現虛引用。

Object obj = new Object(); ReferenceQueue phantomQueue = new ReferenceQueue(); PhantomReference<Object> pf = new PhantomReference<Object>(obj, phantomQueue); obj = null; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue;public class Tess {public static Tess obj; // 當前類對象的聲明static ReferenceQueue<Tess> phantomQueue = null; // 引用隊列public static class CheckRefQueue extends Thread {@Overridepublic void run() {// 操作引用隊列while(true) {if(phantomQueue != null){PhantomReference<Tess> objt = null;try {objt = (PhantomReference<Tess>) phantomQueue.remove(); // 去除最近的虛引用} catch (Exception e) {e.printStackTrace();}if(objt != null){System.out.println("追蹤垃圾回收過程:Tess實例被GC了");}}}}}@Overrideprotected void finalize() throws Throwable {// finalize()方法只能被調用一次super.finalize();System.out.println("調用當前類的finalize()方法");obj = this; // 復活該對象}public static void main(String[] args) {Thread t = new CheckRefQueue();t.setDaemon(true); // 設置為守護線程(程序中沒有非守護線程時,程序結束)t.start();phantomQueue = new ReferenceQueue<Tess>();obj = new Tess();// 構造了Tess對象的虛引用,并制定了引用隊列PhantomReference<Tess> phantomReference = new PhantomReference<Tess>(obj, phantomQueue);try {// 不可獲取虛引用中的對象(null)System.out.println(phantomReference.get());// 將強引用去除obj = null;//第一次GC,由于對象復活,GC無法回收該對象System.gc();Thread.sleep(1000);if(obj == null){System.out.println("obj 為 null");} else {System.out.println("obj 可用");}System.out.println("第二次GC");obj = null;System.gc(); // 一旦將obj對象回收,就會將此虛引用存放到引用隊列中Thread.sleep(1000);if(obj == null){System.out.println("obj 為 null");} else {System.out.println("obj 可用");}} catch (Exception e) {e.printStackTrace();}} }

終結器引用(Final?reference)

1.它用以實現對象的finalize()方法,也可以成為終接器引用。

2.無須手動編碼,其內部配合引用隊列使用。

3.在GC時,終結器引用入隊。由Finalizer線程通過終結器引用找到被引用對象并調用它的finalize()方法,第二次GC時才能回收被引用的對象。

總結

以上是生活随笔為你收集整理的java强引用、软引用、弱引用、虚引用-Java的引用类型总共有四种,你都知道吗的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。