1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        【26期】如何判斷一個對象是否存活?(或者GC對象的判定方法)?

        共 2267字,需瀏覽 5分鐘

         ·

        2020-08-31 02:32

        程序員的成長之路
        互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享?
        關(guān)注


        閱讀本文大概需要 3?分鐘。

        來自:www.jianshu.com/p/09a574dcd5df

        這個問題,面試被問到的概率還是很大的。以下關(guān)于?如何判斷一個對象是否存活?的回答,完全參照《深入理解Java虛擬機》一書,有需要的可以看書學(xué)習(xí)。以下是題目解析
        判斷對象是否存活的算法包括:
        • 引用計數(shù)算法

        • 可達性分析算法

        問題的回答就是通過引用計數(shù)算法或者可達性分析算法去判斷一個對象是否存活,下面開始具體描述這兩種算法。

        引用計數(shù)算法(Reference Counting)

        給對象中添加一個引用計數(shù)器,每當(dāng)有一個地方引用它時,計數(shù)器加1;當(dāng)引用失效時,計數(shù)器值減1;任何時刻計數(shù)器為0的對象就是不能再被引用的。
        例如Object-C,Python語音使用引用計數(shù)算法進行內(nèi)存管理。Java虛擬機沒有選用引用計數(shù)器算法來管理內(nèi)存,其中最主要的原因是它很難解決對象之間相互循環(huán)引用的問題。
        對象循環(huán)引用代碼示例:
        public?class?ReferenceCountingGC?{
        ????public?Object?instance?=?null;

        ????public?static?void?testGC()?{
        ????????ReferenceCountingGC?objA?=?new?ReferenceCountingGC();
        ????????ReferenceCountingGC?objB?=?new?ReferenceCountingGC();
        ????????objA.instance?=?objB;
        ????????objB.instance?=?objA;

        ????????objA?=?null;
        ????????objB?=?null;

        ????????//?假設(shè)在這行發(fā)生GC, objA 和 objB是否能被回收?
        ????????System.gc();
        ????}
        }
        對象objA和objB都有字段instance,賦值令 objA.instance = objB及objB.instance = objA,除此之外,這兩個對象再無任務(wù)引用,實際上這兩個對象已經(jīng)不可能再被訪問,但是它們因為相互引用著對方,導(dǎo)致它們的引用計數(shù)都不為0,于是引用計數(shù)算法無法通知GC收集器回收它們。

        可達性分析算法(Reachability Analysis)

        可達性分析算法的基本思路是通過一系列的稱為“GC Roots”的對象作為起始點,從這些節(jié)點開始向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain),當(dāng)一個對象到GC Root沒有任何引用鏈相連時,則證明此對象是不可用的。

        生存還是死亡

        即使在可達性分析算法中不可達的對象,也并非是“非死不可”的,這時候它們暫時處于“緩刑”階段,要真正宣告一個對象死亡,至少要經(jīng)歷兩次標記過程:如果對象在進行可達性分析后發(fā)現(xiàn)沒有與GC Roots相連接的引用,那它將會被第一次標記并且進行一次篩選,篩選的條件是此對象是否是否有必要執(zhí)行finalize()方法。當(dāng)對象沒有覆蓋finalize()方法,或者finalize()方法已經(jīng)被虛擬機調(diào)用過,虛擬機將這兩種情況都視為“沒有必要執(zhí)行”。
        ??
        如果這個對象被判定為有必要執(zhí)行finalize()方法,那么這個對象將會放置在一個叫做F-Queue的隊列之中。并在稍后由一個虛擬機自動建立的,低優(yōu)先級的Finalizer線程去執(zhí)行它。這里所謂“執(zhí)行”是指虛擬機會觸發(fā)這個方法,但并不承諾會等待它運行結(jié)束,這樣做的原因是,如果有一個對象在finalize()方法中執(zhí)行緩慢,或者發(fā)生死循環(huán),將可能會導(dǎo)致F-Queue隊列中其他對象永久處于等待,甚至導(dǎo)致整個內(nèi)存回收系統(tǒng)崩潰。
        ??
        finalize()方法是對象逃脫死亡命運的最后一次機會,稍后GC將對F-Queue中的對象進行第二次小規(guī)模的標記,如果對象這個時候,未被重新引用,那它基本上就真的被回收了。

        回收方法區(qū)

        Java虛擬機規(guī)范中確實說過可以不要求虛擬機在方法區(qū)中實現(xiàn)垃圾回收,而且在方法區(qū)中進行垃圾回收的“性價比”一般比較低,方法區(qū)的垃圾收集主要回收兩部分內(nèi)容:廢棄的常量和無用的類。
        廢棄的常量,以常量池中字面量的回收為例,假如一個字符串“abc”已經(jīng)進入常量池中,但是當(dāng)前系統(tǒng)已經(jīng)沒有任何一個String對象叫做“abc”的,也沒有任何其他地方引用這個字面量,這個“abc”常量就會被清理出常量池。
        判斷一個無用的類需要同時滿足下面3個條件才能算是“無用的類”
        • 該類的所有實例都已經(jīng)被回收

        • 加載該類的ClassLoader已經(jīng)被回收

        • 該類對應(yīng)的java.lang.Class對象已經(jīng)沒有任何地方被引用,無法在任何地方通過反射訪問該類的方法。

        推薦閱讀:

        【25期】這三道常見的面試題,你有被問過嗎?

        【24期】請你談?wù)剢卫J降膬?yōu)缺點,注意事項,使用場景

        【23期】請你談?wù)勱P(guān)于IO同步、異步、阻塞、非阻塞的區(qū)別

        5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機,樹莓派,等等。在公眾號內(nèi)回復(fù)「2048」,即可免費獲取?。?/span>

        微信掃描二維碼,關(guān)注我的公眾號

        寫留言

        朕已閱?

        瀏覽 35
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            尻逼免费看 | 免费一级AV片 | 国产8页| 精品国产一区一区二区三亚瑟 | 天天爽夜夜爽夜夜爽精品视频 | 久久精品国产亚洲夜色av网站 | 理论片在线观看理伦片 | 欧美一級黃色A片免費看野花 | 草比视频网站 | 操嫩逼网站 |