java 幽灵引用_Java 幽灵引用的作用
原標(biāo)題:Java 幽靈引用的作用
來源:imzoer,
blog.csdn.net/imzoer/article/details/8044900
找實(shí)習(xí)的時(shí)候,面試大摩,就遇到了這個(gè)問題,當(dāng)時(shí)真不該跟面試官交流這個(gè)內(nèi)容的。
垃圾收集過程中,對(duì)象的可觸及狀態(tài)改變的時(shí)候,可以把引用對(duì)象和引用隊(duì)列關(guān)聯(lián)起來【這里說的關(guān)聯(lián),是說垃圾收集器會(huì)把要回收的對(duì)象添加到引用隊(duì)列ReferenceQueue】,這樣在可觸及性發(fā)生變化的時(shí)候得到“通知”。
當(dāng)垃圾收集器對(duì)加入隊(duì)列的對(duì)象改變可觸及性的時(shí)候,就可以收到異步通知了。
看下面的代碼:
package static_;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;
public class Test {
public static boolean isRun = true;
@SuppressWarnings("static-access")
public static void main(String[] args) throws Exception {
String abc = new String("abc");
System.out.println(abc.getClass() + "@" + abc.hashCode());
final ReferenceQueue referenceQueue = new ReferenceQueue();
new Thread() {
public void run() {
while (isRun) {
Object obj = referenceQueue.poll();
if (obj != null) {
try {
Field rereferent = Reference.class
.getDeclaredField("referent");
rereferent.setAccessible(true);
Object result = rereferent.get(obj);
System.out.println("gc will collect:"
+ result.getClass() + "@"
+ result.hashCode() + "t"
+ (String) result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}.start();
PhantomReference abcWeakRef = new PhantomReference(abc,
referenceQueue);
abc = null;
Thread.currentThread().sleep(3000);
System.gc();
Thread.currentThread().sleep(3000);
isRun = false;
}
}
我們用一個(gè)線程檢測(cè)referenceQueue里面是不是有內(nèi)容,如果有內(nèi)容,打印出來queue里面的內(nèi)容。
從這個(gè)例子中,我們可以看出來,虛引用的作用是,我們可以聲明虛引用來引用我們感興趣的對(duì)象,在gc要回收的時(shí)候,gc收集器會(huì)把這個(gè)對(duì)象添加到referenceQueue,這樣我們?nèi)绻麢z測(cè)到referenceQueue中有我們感興趣的對(duì)象的時(shí)候,說明gc將要回收這個(gè)對(duì)象了。此時(shí)我們可以在gc回收之前做一些其他事情,比如記錄些日志什么的。
感謝藍(lán)大牛分享下面的例子。
在java中,finalize函數(shù)本來是設(shè)計(jì)用來在對(duì)象被回收的時(shí)候來做一些操作的(類似C++的析構(gòu)函數(shù))。但是對(duì)象被GC什么時(shí)候回收的時(shí)間,卻是不固定的,這樣finalize函數(shù)很尷尬。虛引用可以用來解決這個(gè)問題。
在創(chuàng)建虛引用的時(shí)候必須傳入一個(gè)引用隊(duì)列。在一個(gè)對(duì)象的finalize函數(shù)被調(diào)用之后,這個(gè)對(duì)象的幽靈引用會(huì)被加入到引用隊(duì)列中。通過檢查隊(duì)列的內(nèi)容就知道對(duì)象是不是要準(zhǔn)備被回收了。
幽靈引用的使用并不多見,主要是實(shí)現(xiàn)細(xì)粒度的內(nèi)存控制。比如下面代碼實(shí)現(xiàn)一個(gè)緩存。程序在確認(rèn)原來的對(duì)象要被回收之后,才申請(qǐng)內(nèi)存創(chuàng)建新的緩存。
在上面的代碼中,每次申請(qǐng)新的緩存的時(shí)候,都要確保之前的字節(jié)數(shù)組被成功回收。引用隊(duì)列的remove方法會(huì)阻塞直到虛引用被加入到引用隊(duì)列中。【只有對(duì)象在內(nèi)存中被移除之后才會(huì)進(jìn)入引用隊(duì)列中】。
不過注意,這種方式可能會(huì)導(dǎo)致gc次數(shù)過多,程序吞吐量下降。
另外注意,system.gc調(diào)用僅僅是建議虛擬機(jī)進(jìn)行回收,并不一定馬上會(huì)進(jìn)行g(shù)c。返回搜狐,查看更多
責(zé)任編輯:
總結(jié)
以上是生活随笔為你收集整理的java 幽灵引用_Java 幽灵引用的作用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 升级12代i5+2.8K OLED屏:宏
- 下一篇: AMD Zen4锐龙未发布就被开盖:变了