欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Java回收對象的標記和對象的二次標記過程

 更新時間:2017年10月10日 11:02:12   作者:馬克吐溫  
這篇文章主要介紹了淺談Java回收對象的標記和對象的二次標記過程的相關(guān)內(nèi)容,小編覺得還是挺不錯的,這里給大家分享一下,需要的朋友可以參考。

一、對象的標記

1、什么是標記?怎么標記? 

        第一個問題相信大家都知道,標記就是對一些已死的對象打上記號,方便垃圾收集器的清理。 至于怎么標記,一般有兩種方法:引用計數(shù)和可達性分析。

引用計數(shù)實現(xiàn)起來比較簡單,就是給對象添加一個引用計數(shù)器,每當有一個地方引用它時就加1,引用失效時就減1,當計數(shù)器為0的時候就標記為可回收。這種判斷效率很高,但是很多主流的虛擬機并沒有采用這種方法,主要是因為它很難解決幾個對象之間循環(huán)引用的問題,雖然不怎么用了,但還是值得我們學(xué)習(xí)!

public class Test {
private Object obj;
Public static void main(){
Test t1=new Test();
Test t2=new Test();
t1.obj=t2;
t2.obj=t1;
t1=null;
t2=null;
//如果對象在這行發(fā)生gc,那么t1和t2對象是否能被回收
System.gc();
}
}

 可達性分析的基本思路就是:通過將一些稱為"GC Roots"的對象作為起始點,從這些節(jié)點開始搜索,搜索和該節(jié)點發(fā)生直接或者間接引用關(guān)系的對象,將這些對象以鏈的形式組合起來,形成一張“關(guān)系網(wǎng)”,又叫做引用鏈。最后垃圾收集器就回收一些不在這張關(guān)系網(wǎng)上的對象。如圖:

連接GC Roots對象的object是確定還存活的對象,而右邊的die obj由于和GCROOTS沒有關(guān)系,所以會標記為可回收的對象。目前主流的商用虛擬機用的都是類似的方法。那什么對象才能作為“GC Roots”呢?在java中,有四種對象可以作為“GC Roots”

        1:棧幀(第一章的名詞)中的引用對象。(棧中的)

        2:靜態(tài)屬性引用的對象。(方法區(qū)中的)

        3:常量引用的對象。(方法區(qū)中的)

        4:本地方法棧中JNI引用的對象。(本地方法棧中的)

二、對象的二次回收

說過對象的標記,但是不是被標記了就肯定會被回收呢?不知道小伙伴們記不記得Object類有一個finalize()方法,所有類都繼承了Object類,因此也默認實現(xiàn)了這個方法。

finalize的工作原理應(yīng)該是這樣的:一旦垃圾收集器準備好釋放對象占用的存儲空間,它首先調(diào)用finalize(),而且只有在下一次垃圾收集過程中,才會真正回收對象的內(nèi)存.所以如果使用finalize(),就可以在垃圾收集期間進行一些重要的清除或清掃工作.
finalize()在什么時候被調(diào)用?

有三種情況

1.所有對象被Garbage Collection時自動調(diào)用,比如運行System.gc()的時候.

2.程序退出時為每個對象調(diào)用一次finalize方法。

3.顯式的調(diào)用finalize方法

這個方法的用途就是:在該對象被回收之前,該對象的finalize()方法會被調(diào)用。這里的回收之前指的就是被標記之后,問題就出在這里,有沒有一種情況就是原本一個對象開始不再上一章所講的“關(guān)系網(wǎng)”(引用鏈)中,但是當開發(fā)者重寫了finalize()后,并且將該對象重新加入到了“關(guān)系網(wǎng)”中,也就是說該對象對我們還有用,不應(yīng)該被回收,但是已經(jīng)被標記啦,怎么辦呢?

        針對這個問題,虛擬機的做法是進行兩次標記,即第一次標記不在“關(guān)系網(wǎng)”中的對象。第二次的話就要先判斷該對象有沒有實現(xiàn)finalize()方法了,如果沒有實現(xiàn)就直接判斷該對象可回收;如果實現(xiàn)了就會先放在一個隊列中,并由虛擬機建立的一個低優(yōu)先級的線程去執(zhí)行它,隨后就會進行第二次的小規(guī)模標記,在這次被標記的對象就會真正的被回收了。

總結(jié):簡單說,對象先進行第一次標記,在下一次GC之前會執(zhí)行對象的finalize()方法。在執(zhí)行finalize()方法的時候判斷對象是否實現(xiàn)了finalize()方法,沒有實現(xiàn)直接清除;實現(xiàn)了,將對象放在一個隊列中執(zhí)行finalize方法,進行第二次標記
在java根搜索算法中判斷對象的可達性,對于不可達的對象,也并不一定是必須清理。這個時候有一個緩刑期,真正的判斷一個對象死亡,至少要經(jīng)過倆次標記過程:如果對象在進行根搜索后發(fā)現(xiàn)沒有與GC roots相關(guān)聯(lián)的引用鏈,那他將會第一次標記并且進行一次篩選,篩選的條件是此對象是否有必要執(zhí)行finalize()方法,當對象沒有覆蓋finalize()方法,或者finalize()方法已經(jīng)被虛擬機調(diào)用過,虛擬機將這倆種情況都視為“沒有必要執(zhí)行”。

即當一個對象重寫了finalize()方法的時候,這個對象被判定為有必要執(zhí)行finalize()方法,那么這個對象被放置在F-Queue隊列之中,并在稍后由一條由虛擬機自動建立的、低優(yōu)先級的Finalizer線程去執(zhí)行。這里所謂的執(zhí)行是指虛擬機會出發(fā)這個方法,但不承諾會等待它運行結(jié)束。這樣做的原因:如果一個對象在finalize()方法中執(zhí)行緩慢,或者發(fā)生了死循環(huán)(極端的情況下),將可能會導(dǎo)致F-Queue隊列中的其他對象永久處于等待狀態(tài),甚至導(dǎo)致整個內(nèi)存回收系統(tǒng)崩潰。finalize()方法是對象逃脫死亡命運的最后一次機會,稍后GC將對F-Queue中的對象進行第二次小規(guī)模的標記,如果對象要在finalize()中成功拯救自己----只要重新與引用鏈上的任何建立關(guān)聯(lián)即可,那么在第二次標記時它將會被移出“即將回收”的集合;如果對象這時候沒有逃脫,就會被回收。代碼示例:參考《深入理解java虛擬機》對應(yīng)章節(jié)

總結(jié)

以上就是本文關(guān)于淺談Java回收對象的標記和對象的二次標記過程的全部內(nèi)容,希望對大家學(xué)習(xí)Java有所幫助。感興趣的朋友可以參閱:Java虛擬機裝載和初始化一個class類代碼解析 、Java編程思想對象的容納實例詳解、Java系統(tǒng)的高并發(fā)解決方法詳解等,有什么問題可以隨時留言,小編會及時回復(fù)大家的。

相關(guān)文章

  • SpringBoot使用MyBatis-Plus解決Invalid?bound?statement異常

    SpringBoot使用MyBatis-Plus解決Invalid?bound?statement異常

    這篇文章主要介紹了SpringBoot使用MyBatis-Plus解決Invalid?bound?statement異常,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • Java8學(xué)習(xí)教程之lambda表達式語法介紹

    Java8學(xué)習(xí)教程之lambda表達式語法介紹

    眾所周知lambda表達式是JAVA8中提供的一種新的特性,它支持Java也能進行簡單的“函數(shù)式編程”。 下面這篇文章主要給大家介紹了關(guān)于Java8學(xué)習(xí)教程之lambda表達式語法的相關(guān)資料,需要的朋友可以參考下。
    2017-09-09
  • 詳解基于JWT的springboot權(quán)限驗證技術(shù)實現(xiàn)

    詳解基于JWT的springboot權(quán)限驗證技術(shù)實現(xiàn)

    這篇文章主要介紹了詳解基于JWT的springboot權(quán)限驗證技術(shù)實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • java實現(xiàn)簡單TCP聊天程序

    java實現(xiàn)簡單TCP聊天程序

    這篇文章主要為大家詳細介紹了java實現(xiàn)簡單TCP聊天程,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • java排序算法之_選擇排序(實例講解)

    java排序算法之_選擇排序(實例講解)

    下面小編就為大家?guī)硪黄猨ava排序算法之_選擇排序(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 淺談Java對象禁止使用基本類型

    淺談Java對象禁止使用基本類型

    本文主要介紹了淺談Java對象禁止使用基本類型,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • springboot整合freemarker代碼自動生成器

    springboot整合freemarker代碼自動生成器

    最近做了一個工具,可以實現(xiàn)代碼自動生成,今天整理出來分享給大家,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • RocketMQ的四種常用消息隊列及代碼演示

    RocketMQ的四種常用消息隊列及代碼演示

    這篇文章主要介紹了RocketMQ的四種常用消息隊列及代碼演示,普通消息隊列是最基本的一種消息隊列,可以按照先進先出(FIFO)的順序存儲消息,并且可以被多個消費者同時消費,可以通過在生產(chǎn)者端指定主題名稱和標簽來創(chuàng)建普通消息隊列,需要的朋友可以參考下
    2024-01-01
  • Java/Web調(diào)用Hadoop進行MapReduce示例代碼

    Java/Web調(diào)用Hadoop進行MapReduce示例代碼

    本篇文章主要介紹了Java/Web調(diào)用Hadoop進行MapReduce示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • java異常處理機制示例(java拋出異常、捕獲、斷言)

    java異常處理機制示例(java拋出異常、捕獲、斷言)

    這篇文章主要介紹了java異常處理機制示例(java拋出異常、捕獲、斷言),需要的朋友可以參考下
    2014-05-05

最新評論