一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 詳解java中Reference的實現與相應的執行過程

詳解java中Reference的實現與相應的執行過程

2020-06-14 11:47i flym JAVA教程

不知道大家知不知道特殊的reference對象都是被jvm專門處理的,所以這篇文章就相應的工作流程和referencequeue之間的協作進行梳理.有需要的朋友們可以參考借鑒。

一、Reference類型(除強引用)

可以理解為Reference的直接子類都是由jvm定制化處理的,因此在代碼中直接繼承于Reference類型沒有任何作用.只能繼承于它的子類,相應的子類類型包括以下幾種.(忽略沒有在java中使用的,如jnireference)

     SoftReference

     WeakReference

     FinalReference

     PhantomReference

上面的引用類型在相應的javadoc中也有提及.FinalReference專門為finalize方法設計,另外幾個也有特定的應用場景.其中softReference用在內存相關的緩存當中,weakReference用在與回收相關的大多數場景.phantomReference用在與包裝對象回收回調場景當中(比如資源泄漏檢測).

可以直接在ide中查看幾個類型的子類信息,即可了解在大多數框架中,都是通過繼承相應的類型用在什么場景當中,以便于我們實際進行選型處理.

二、Reference構造函數

其內部提供2個構造函數,一個帶queue,一個不帶queue.其中queue的意義在于,我們可以在外部對這個queue進行監控.即如果有對象即將被回收,那么相應的reference對象就會被放到這個queue里.我們拿到reference,就可以再作一些事務.

而如果不帶的話,就只有不斷地輪訓reference對象,通過判斷里面的get是否返回null(phantomReference對象不能這樣作,其get始終返回null,因此它只有帶queue的構造函數).這兩種方法均有相應的使用場景,取決于實際的應用.如weakHashMap中就選擇去查詢queue的數據,來判定是否有對象將被回收.而ThreadLocalMap,則采用判斷get()是否為null來作處理.

相應的構造函數如下所示:

?
1
2
3
4
5
6
7
8
Reference(T referent) {
 this(referent, null);
}
 
Reference(T referent, ReferenceQueue<? super T> queue) {
 this.referent = referent;
 this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}

這里面的NULL隊列,即可以理解為不需要對其隊列中的數據作任何處理的隊列.并且其內部也不會存取任何數據.

在上面的對象中,referent表示其引用的對象,即我們在構造的時候,需要被包裝在其中的對象.對象即將被回收的定義即此對象除了被reference引用之外沒有其它引用了(并非確實沒有被引用,而是gcRoot可達性不可達,以避免循環引用的問題).

queue即是對象即被回收時所要通知的隊列,當對象即被回收時,整個reference對象(而不是被回收的對象)會被放到queue里面,然后外部程序即可通過監控這個queue拿到相應的數據了.

三、ReferenceQueue及Reference引用鏈

這里的queue名義上是一個隊列,但實際內部并非有實際的存儲結構,它的存儲是依賴于內部節點之間的關系來表達.可以理解為queue是一個類似于鏈表的結構,這里的節點其實就是reference本身.可以理解為queue為一個鏈表的容器,其自己僅存儲當前的head節點,而后面的節點由每個reference節點自己通過next來保持即可.

Reference狀態值

每個引用對象都有相應的狀態描述,即描述自己以及包裝的對象當前處于一個什么樣的狀態,以方便進行查詢,定位或處理.

     1、Active:活動狀態,即相應的對象為強引用狀態,還沒有被回收,這個狀態下對象不會放到queue當中.在這個狀態下next為null,queue為定義時所引用的queue.

     2、Pending:準備放入queue當中,在這個狀態下要處理的對象將挨個地排隊放到queue當中.在這個時間窗口期,相應的對象為pending狀態.不管什么reference,進入到此狀態的,即可認為相應的此狀態下,next為自己(由jvm設置),queue為定義時所引用的queue.

     3、Enqueued:相應的對象已經為待回收,并且相應的引用對象已經放到queue當中了.準備由外部線程來詢循queue獲取相應的數據.此狀態下,next為下一個要處理的對象,queue為特殊標識對象ENQUEUED.

     4、Inactive:即此對象已經由外部從queue中獲取到,并且已經處理掉了.即意味著此引用對象可以被回收,并且對內部封裝的對象也可以被回收掉了(實際的回收運行取決于clear動作是否被調用).可以理解為進入到此狀態的肯定是應該被回收掉的.

jvm并不需要定義狀態值來判斷相應引用的狀態處于哪個狀態,只需要通過計算next和queue即可進行判斷.

四、ReferenceQueue#head

始終保存當前隊列中最新要被處理的節點,可以認為queue為一個后進先出的隊列.當新的節點進入時,采取以下的邏輯

?
1
newE.next = head;head=newE;

然后,在獲取的時候,采取相應的邏輯

?
1
tmp = head;head=tmp.next;return tmp;

五、Reference#next

即描述當前引用節點所存儲的下一個即將被處理的節點.但next僅在放到queue中才會有意義.為了描述相應的狀態值,在放到隊列當中后,其queue就不會再引用這個隊列了.而是引用一個特殊的ENQUEUED.因為已經放到隊列當中,并且不會再次放到隊列當中.

六、Reference#referent

即描述當前引用所引用的實際對象,正如在注解中所述,其會被仔細地處理.即此什么什么時候會被回收,如果一旦被回收,則會直接置為null,而外部程序可通過通過引用對象本身(而不是referent)了解到,回收行為的產生.

七、ReferenceQueue#enqueue 待處理引用入隊

此過程即在reference對象從active->pending->enqued的過程. 此方法為處理pending狀態的對象為enqued狀態.相應的過程即為之前的邏輯,即將一個節點入隊操作,相應的代碼如下所示.

?
1
2
3
4
5
r.queue = ENQUEUED;
r.next = (head == null) ? r : head;
head = r;
queueLength++;
lock.notifyAll();

最后的nitify即通知外部程序之前阻塞在當前隊列之上的情況.(即之前一直沒有拿到待處理的對象)

八、Reference#tryHandlePending

即處理reference對象從active到pending狀態的變化.在Reference對象內部,有一個static字段,其相應的聲明如下:

?
1
2
3
4
5
6
/* List of References waiting to be enqueued. The collector adds
 * References to this list, while the Reference-handler thread removes
 * them. This list is protected by the above lock object. The
 * list uses the discovered field to link its elements.
 */
private static Reference<Object> pending = null;

可以理解為jvm在gc時會將要處理的對象放到這個靜態字段上面.同時,另一個字段discovered,表示要處理的對象的下一個對象.即可以理解要處理的對象也是一個鏈表,通過discovered進行排隊,這邊只需要不停地拿到pending,然后再通過discovered不斷地拿到下一個對象即可.因為這個pending對象,兩個線程都可能訪問,因此需要加鎖處理.

相應的處理過程如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
if (pending != null) {
 r = pending;
 // 'instanceof' might throw OutOfMemoryError sometimes
 // so do this before un-linking 'r' from the 'pending' chain...
 c = r instanceof Cleaner ? (Cleaner) r : null;
 // unlink 'r' from 'pending' chain
 pending = r.discovered;
 r.discovered = null;
}
//將處理對象入隊,即進入到enqued狀態
ReferenceQueue<? super Object> q = r.queue;
if (q != ReferenceQueue.NULL) q.enqueue(r);

九、Reference#clear

清除引用對象所引用的原對象,這樣通過get()方法就不能再訪問到原對象了.從相應的設計思路來說,既然都進入到queue對象里面,就表示相應的對象需要被回收了,因為沒有再訪問原對象的必要.此方法不會由JVM調用,而jvm是直接通過字段操作清除相應的引用,其具體實現與當前方法相一致.

clear的語義就是將referent置null.

     WeakReference對象進入到queue之后,相應的referent為null.

     SoftReference對象,如果對象在內存足夠時,不會進入到queue,自然相應的reference不會為null.如果需要被處理(內存不夠或其它策略),則置相應的referent為null,然后進入到queue.

     FinalReference對象,因為需要調用其finalize對象,因此其reference即使入queue,其referent也不會為null,即不會clear掉.

     PhantomReference對象,因為本身get實現為返回null.因此clear的作用不是很大.因為不管enqueue還是沒有,都不會清除掉.

十、ReferenceHandler enqueue線程

上面提到jvm會將要處理的對象設置到pending對象當中,因此肯定有一個線程來進行不斷的enqueue操作,此線程即引用處理器線程,其優先級為MAX_PRIORITY,即最高.相應的啟動過程為靜態初始化創建,可以理解為當任何使用到Reference對象或類時,此線程即會被創建并啟動.相應的代碼如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
static {
 ThreadGroup tg = Thread.currentThread().getThreadGroup();
 for (ThreadGroup tgn = tg;
   tgn != null;
   tg = tgn, tgn = tg.getParent());
 Thread handler = new ReferenceHandler(tg, "Reference Handler");
 /* If there were a special system-only priority greater than
  * MAX_PRIORITY, it would be used here
  */
 handler.setPriority(Thread.MAX_PRIORITY);
 handler.setDaemon(true);
 handler.start();
}

其優先級最高,可以理解為需要不斷地處理引用對象.在通過jstack打印運行線程時,相應的Reference Handler即是指在這里初始化的線程,如下所示:

詳解java中Reference的實現與相應的執行過程

十一、JVM相關

在上述的各個處理點當中,都與JVM的回收過程相關.即認為gc流程會與相應的reference協同工作.如使用cms收集器,在上述的整個流程當中,涉及到preclean過程,也涉及到softReference的重新標記處理等,同時對reference對象的各種處理也需要與具體的類型相關進行協作.相應的JVM處理,采用C++代碼,因此需要好好地再理一下.

十二、總結

與finalReference對象相同,整個reference和referenceQueue都是一組協同工作的處理組,為保證不同的引用語義,通過與jvm gc相關的流程一起作用,最終實現不同場景,不同引用級別的處理.

另外,由于直接使用referenceQueue,再加上開啟線程去監控queue太過麻煩和復雜.可以參考由google guava實現的 FinalizableReferenceQueue 以及相應的FinalizableReference對象.可以簡化一點點處理過程.以上就是這篇文章的全部內容,希望對大家的學習或者工作帶來一定的幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩成人免费aa在线看 | 高跟丝袜hdvideossex | 久久视频在线视频观看天天看视频 | 国产卡一卡二卡三乱码手机 | 99热er| 久久精品国产亚洲AV蜜臀 | 91麻豆影视 | 欧美日本一道高清免费3区 欧美人做人爱a全程免费 | 精品推荐国产麻豆剧传媒 | 日韩高清一区 | 国产精品成人网红女主播 | 激情文学综合网 | 亚洲国产精品无码中文在线 | 日本护士xxxx爽爽爽 | 黑人艹逼 | 91精品国产9l久久久久 | 精品精品国产自在久久高清 | 无人区在线观看免费国语完整版 | 欧美亚洲国产一区二区三区 | 香港论理午夜电影网 | 草莓绿巨人香蕉茄子芭乐 | 亚洲成a人不卡在线观看 | 色呦阁| 国产永久在线观看 | 99热精品在线免费观看 | 亚洲欧美专区精品久久 | 免费一区在线 | a级亚洲片精品久久久久久久 | 日韩欧美亚洲国产高清在线 | 日本三级免费观看 | 日本护士撒尿xxxxhd | 欧美在线视频免费播放 | 国产乱子伦在线观看不卡 | 波多野结衣178部中文字幕 | 午夜一区二区三区 | 婷婷色伊人 | 国产精品久久久久久影院 | 亚洲男人天堂网站 | 91国内精品久久久久怡红院 | 手机亚洲第一页 | 国产亚洲精品精品国产亚洲综合 |