搜尋
首頁Javajava教程詳解Java Reference源碼分析程式碼

@(Java)[Reference]

Java Reference 原始碼分析

  Reference物件封裝了其它物件的引用,可以和普通的物件一樣操作,在在一定的限制條件下,支援和垃圾收集器的交互作用。即可以使用Reference對象來引用其它對象,但最後還是會被垃圾收集器回收。程序有時也需要在物件回收後被通知,以告知對象的可及性發生變更。
  Java提供了四種不同類型的引用,引用等級從高到低分別為FinalReference,SoftReference,WeakReference,PhantomReference。其中FinalReference並未對外提供使用。每種類型對應著不同程度的可及性。

簡介

強引用FinalReference

#強引用指的是,程式中有直接可達的引用,而不需要透過任何引用對象,如Object obj = new Object();中,obj為強引用。

軟引用SoftReference

軟引用,非強引用,但可以透過軟引用物件來存取。軟引用的對象,只有在記憶體不足的時候(拋出OOM異常前),垃圾收集器會決定回收該軟引用所指向的對象。軟引用通常用於實現記憶體敏感的快取。

SoftReference<object> softRef = new SoftReference<object>(new Object());</object></object>

弱引用WeakReference

弱引用,非強引用和軟引用,但可以透過弱引用物件來存取。弱引用的對象,不管記憶體是否足夠,只要被垃圾收集器發現,該引用的對象就會被回收。實際的應用請見WeakHashMap等。

WeakReference<object> weakRef = new WeakReference<object>(new Object());</object></object>

虛引用PhantomReference

虛引用,該引用必須和引用隊列(ReferenceQueue)一起使用,一般用於實現追蹤垃圾收集器的回收動作,例如在物件被回收的時候,會呼叫該物件的finalize方法,在使用虛引用可以實現該動作,也更加安全。

Object obj = new Object();
ReferenceQueue<object> refQueue = new ReferenceQueue();
PhantomReference<object> phantom = new PhantomReference<object>(obj, refQueue);</object></object></object>

ReferenceQueue

該隊列作為引用中的一員,可以和上述三種引用類型組合使用,該隊列的作用是:建立Reference時,將Queue註冊到Reference中,當該Reference所引用的物件被垃圾收集器回收時,會將該Reference放到該佇列中,相當於一種通知機制。
範例Demo1:

ReferenceQueue queue = new ReferenceQueue();
WeakReference reference = new WeakReference(new Object(), queue);
System.out.println(reference);
System.gc();
Reference reference1 = queue.remove();
System.out.println(reference1);

原始碼分析

Reference和ReferenceQueue

Reference內部有幾個比較重要的屬性

// 用于保存对象的引用,GC会根据不同Reference来特别对待
private T referent;
// 如果需要通知机制,则保存的对对应的队列
ReferenceQueue super T> queue;
/* 这个用于实现一个单向循环链表,用以将保存需要由ReferenceHandler处理的引用 */
Reference next;
static private class Lock { };
// 锁,用于同步pending队列的进队和出队
private static Lock lock = new Lock();
// 此属性保存一个PENDING的队列,配合上述next一起使用
private static Reference pending = null;

狀態

详解Java Reference源码分析代码

內部類別ReferenceHandler

#ReferenceHandler作為Reference的靜態內部類,用於實作將pending佇列裡面的Reference實例依序加入不同的ReferenceQueue中(取決於Reference裡面的queue)。此pending的元素由GC負責加入。
註:這裡對pending佇列進行加鎖,個人認為是因為GC執行緒可能和ReferenceHandler所在的執行緒並發執行,如GC採用CMS並發收集的時候。
如下程式碼所示

// 此线程在静态块中启动,即一旦使用了Reference,则会启动该线程
private static class ReferenceHandler extends Thread {
    public void run() {
        for (;;) {

            Reference r;
            synchronized (lock) {
                if (pending != null) {
                    r = pending;
                    Reference rn = r.next;
                    // 从pending中取下一个元素,如果后继为空,则next指向自身                    pending = (rn == r) ? null : rn;
                    r.next = r;
                } else {
                    try {
                        // 没有则等待,后续加入元素会调用lock.notify唤醒
                        lock.wait();
                    } catch (InterruptedException x) { }
                    continue;
                }
            }
            // ...
            ReferenceQueue q = r.queue;
            // 如果该Reference注册了对应的Queue,则加入到该Queue中
            if (q != ReferenceQueue.NULL) q.enqueue(r);
        }
    }
}

ReferenceQueue屬性

// 用于标识没有注册Queue
static ReferenceQueue NULL = new Null();
// 用于标识已经处于对应的Queue中
static ReferenceQueue ENQUEUED = new Null();

static private class Lock { };
/* 互斥锁,用于同步ReferenceHandler的enqueue和用户线程操作的remove和poll出队操作 */
private Lock lock = new Lock();
// 队列
private volatile Reference extends T> head = null;
// 队列中的元素个数
private long queueLength = 0;

ReferenceQueue.enqueue

只會透過Reference裡要呼叫該方法,用於將Reference放入到目前佇列中

boolean enqueue(Reference extends T> r) {    synchronized (r) {        // 判断是否已经入队了
        if (r.queue == ENQUEUED) return false;        synchronized (lock) {
            r.queue = ENQUEUED;            // 单向循环
            r.next = (head == null) ? r : head;
            head = r;
            queueLength++;            if (r instanceof FinalReference) {
                sun.misc.VM.addFinalRefCount(1);
            }            // 通知当前挂起的线程(调用remove时有可能会挂起)
            lock.notifyAll();            return true;
        }
    }
}

ReferenceQueue.remove

public Reference extends T> remove(long timeout)    throws IllegalArgumentException, InterruptedException
{    if (timeout  r = reallyPoll();        // 如果不为空,则直接返回
        if (r != null) return r;        for (;;) {            // 否则等待,由enqueue时notify唤醒
            lock.wait(timeout);
            r = reallyPoll();            if (r != null) return r;            if (timeout != 0) return null;
        }
    }
}

具體執行流程

以上述範例Demo1作為分析

// 创建一个引用队列
ReferenceQueue queue = new ReferenceQueue();

// 创建虚引用,此时状态为Active,并且Reference.pending为空,当前Reference.queue = 上面创建的queue,并且next=null
WeakReference reference = new WeakReference(new Object(), queue);
System.out.println(reference);
// 当GC执行后,由于是虚引用,所以回收该object对象,并且置于pending上,此时reference的状态为PENDING
System.gc();

/* ReferenceHandler从pending中取下该元素,并且将该元素放入到queue中,此时Reference状态为ENQUEUED,Reference.queue = ReferenceENQUEUED */

/* 当从queue里面取出该元素,则变为INACTIVE,Reference.queue = Reference.NULL */
Reference reference1 = queue.remove();
System.out.println(reference1);

以上是詳解Java Reference源碼分析程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JVM如何促進Java的'寫作一次,在任何地方運行”(WORA)功能?JVM如何促進Java的'寫作一次,在任何地方運行”(WORA)功能?May 02, 2025 am 12:25 AM

JVM通過字節碼解釋、平台無關的API和動態類加載實現Java的WORA特性:1.字節碼被解釋為機器碼,確保跨平台運行;2.標準API抽像操作系統差異;3.類在運行時動態加載,保證一致性。

Java的較新版本如何解決平台特定問題?Java的較新版本如何解決平台特定問題?May 02, 2025 am 12:18 AM

Java的最新版本通過JVM優化、標準庫改進和第三方庫支持有效解決平台特定問題。 1)JVM優化,如Java11的ZGC提升了垃圾回收性能。 2)標準庫改進,如Java9的模塊系統減少平台相關問題。 3)第三方庫提供平台優化版本,如OpenCV。

說明JVM執行的字節碼驗證的過程。說明JVM執行的字節碼驗證的過程。May 02, 2025 am 12:18 AM

JVM的字節碼驗證過程包括四個關鍵步驟:1)檢查類文件格式是否符合規範,2)驗證字節碼指令的有效性和正確性,3)進行數據流分析確保類型安全,4)平衡驗證的徹底性與性能。通過這些步驟,JVM確保只有安全、正確的字節碼被執行,從而保護程序的完整性和安全性。

平台獨立性如何簡化Java應用程序的部署?平台獨立性如何簡化Java應用程序的部署?May 02, 2025 am 12:15 AM

Java'splatFormIndepentEncealLowsApplicationStorunonAnyOperatingsystemwithajvm.1)singleCodeBase:writeandeandcompileonceforallplatforms.2)easileupdates:updatebybytecodeforsimultanane deployment.3)testOnOneOnePlatForforurouniverSalpeforuluniverSalpehavior formafforulululyiversalivernave.444.44.444

Java的平台獨立性如何隨著時間的流逝而發展?Java的平台獨立性如何隨著時間的流逝而發展?May 02, 2025 am 12:12 AM

Java的平台獨立性通過JVM、JIT編譯、標準化、泛型、lambda表達式和ProjectPanama等技術不斷增強。自1990年代以來,Java從基本的JVM演進到高性能的現代JVM,確保了代碼在不同平台的一致性和高效性。

在Java應用程序中緩解平台特定問題的策略是什麼?在Java應用程序中緩解平台特定問題的策略是什麼?May 01, 2025 am 12:20 AM

Java如何緩解平台特定的問題? Java通過JVM和標準庫來實現平台無關性。 1)使用字節碼和JVM抽像操作系統差異;2)標準庫提供跨平台API,如Paths類處理文件路徑,Charset類處理字符編碼;3)實際項目中使用配置文件和多平台測試來優化和調試。

Java的平台獨立性與微服務體系結構之間有什麼關係?Java的平台獨立性與微服務體系結構之間有什麼關係?May 01, 2025 am 12:16 AM

java'splatformentenceenhancesenhancesmicroservicesharchitecture byferingDeploymentFlexible,一致性,可伸縮性和便攜性。 1)DeploymentFlexibilityAllowsibilityAllowsOllowsOllowSorlowsOllowsOllowsOllowSeStorunonAnyPlatformwithajvM.2)penterencyCrossServAccAcrossServAcrossServiCessImplifififiesDeevelopmentandeDe

GRAALVM與Java的平台獨立目標有何關係?GRAALVM與Java的平台獨立目標有何關係?May 01, 2025 am 12:14 AM

GraalVM通過三種方式增強了Java的平台獨立性:1.跨語言互操作,允許Java與其他語言無縫互操作;2.獨立的運行時環境,通過GraalVMNativeImage將Java程序編譯成本地可執行文件;3.性能優化,Graal編譯器生成高效的機器碼,提升Java程序的性能和一致性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境