java中的引用類型之強軟弱虛詳解
前言
java中的引用類型共4種:強軟弱虛,具體每種類型的特點和應(yīng)用場景。記錄下。本文是看了馬士兵老師的視頻后記錄整理的。加深印象。
基本概念
1. 強引用
強引用是使用最普遍的引用。如果一個對象具有強引用,那垃圾回收器絕不會回收它。當內(nèi)存空間不足時,Java虛擬機寧愿拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內(nèi)存不足的問題。

顯式地設(shè)置M對象為null,或讓其超出對象的生命周期范圍,則gc認為該對象不存在引用,這時就可以回收這個對象
示例代碼
聲明一個M類
public class M {
/**
* 當這個對象會被回收的時候,finalize會被調(diào)用
*
* @throws Throwable
*/
@Override
protected void finalize() throws Throwable {
System.out.println("finalize");
}
}
強引用調(diào)用
public class NormalReference {
public static void main(String[] args) throws IOException {
M m = new M();
m = null;
System.gc();
// 如果不寫 main方法退出。System.gc()在垃圾回收線程里;
// 有可能還沒來得及回收main方法就退出了
System.in.read();
}
}
輸出結(jié)果
finalize
2. 軟引用
軟引用對象是在jvm內(nèi)存不夠的時候才會被回收

代碼示例
public class Soft {
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);
//10m
SoftReference<byte[]> m = new SoftReference<>(new byte[1024 * 1024 * 10]);
System.out.println(m.get());
System.gc();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(m.get());
// 再分配一個數(shù)組,heap裝不下去,這時候系統(tǒng)會垃圾回收,
// 先回收一次,如果不夠,會把軟引用回收
byte[] b = new byte[1024 * 1024 * 11];
System.out.println(m.get());
}
}
設(shè)置程序運行參數(shù): -Xmx20M
運行結(jié)果
19
[B@1540e19d
[B@1540e19d
null
我們可以看到,這個時候已經(jīng)被回收了。
應(yīng)用場景:軟引用時候做緩存
3. 弱引用
弱引用與軟引用的區(qū)別在于:只具有弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象,不管當前內(nèi)存空間足夠與否,都會回收它的內(nèi)存
代碼示例
public class Weak {
public static void main(String[] args) {
WeakReference<M> m = new WeakReference<>(new M());
System.out.println(m.get());
System.gc();
System.out.println(m.get());
}
}
執(zhí)行結(jié)果
M@1540e19d
null
finalize
4. 虛引用
如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。
虛引用必須和引用隊列(ReferenceQueue)聯(lián)合使用。當垃圾回收器準備回收一個對象時,如果發(fā)現(xiàn)它還有虛引用,就會在回收對象的內(nèi)存之前,把這個虛引用加入到與之關(guān)聯(lián)的引用隊列中。

示例
public class Phantom {
private static final List<Object> LIST = new LinkedList<>();
private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();
public static void main(String[] args) {
PhantomReference<M> phantomReference = new PhantomReference<>(new M(), QUEUE);
new Thread(
() -> {
while (true) {
LIST.add(new byte[1024 * 1024]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(phantomReference.get());
}
}
).start();
new Thread(() -> {
while (true) {
Reference<? extends M> poll = QUEUE.poll();
if (poll != null) {
System.out.println("-------虛引用對象被jvm回收了------" + poll);
}
}
}).start();
}
}
運行結(jié)果
finalize
null
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
at Phantom.lambda$main$0(Phantom.java:18)
at Phantom$$Lambda$1/1078694789.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
-------虛引用對象被jvm回收了------java.lang.ref.PhantomReference@688ee48d
應(yīng)用場景:堆外內(nèi)存的管理
總結(jié)
到此這篇關(guān)于java中引用類型之強軟弱虛的文章就介紹到這了,更多相關(guān)java引用類型之強軟弱虛內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java數(shù)據(jù)結(jié)構(gòu)超詳細分析二叉搜索樹
二叉搜索樹是以一棵二叉樹來組織的。每個節(jié)點是一個對象,包含的屬性有l(wèi)eft,right,p和key,其中,left指向該節(jié)點的左孩子,right指向該節(jié)點的右孩子,p指向該節(jié)點的父節(jié)點,key是它的值2022-03-03
淺析Java數(shù)據(jù)庫操作工具包jOOQ的使用
jOOQ?是一個輕量級的?Java?ORM(對象關(guān)系映射)框架,可用來構(gòu)建復(fù)雜的?SQL?查詢,這篇文章主要來和大家介紹一下jOOQ的使用,需要的可以參考下2024-04-04
MapStruct內(nèi)部錯誤:NullPointerException的解決方案
在Java開發(fā)中,MapStruct是一個非常流行的對象映射工具,它通過注解處理器在編譯時生成映射代碼,極大地簡化了對象之間的轉(zhuǎn)換操作,本文將詳細分析一個常見的MapStruct內(nèi)部錯誤——NullPointerException,并提供一系列解決方案,需要的朋友可以參考下2025-02-02
使用SkyWalking監(jiān)控Java服務(wù)的過程
這篇文章主要介紹了使用SkyWalking監(jiān)控Java服務(wù),介紹一個對源碼0入侵的Java服務(wù)監(jiān)控方式,SkyWalking Agent,只需要啟動Java程序的時候加幾個參數(shù),就能對Java服務(wù)進行可視化監(jiān)控,需要的朋友可以參考下2023-08-08

