亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

JVM 是否會收集不再使用的局部變量引用的對象?

JVM 是否會收集不再使用的局部變量引用的對象?

墨色風雨 2022-07-14 09:33:01
據我所知,方法的局部變量位于執行線程的堆棧幀中,局部變量的引用類型只有對象的引用,而不是對象本身。JVM 中的所有對象都位于堆空間中。我想知道正在執行的方法中由局部變量引用的對象在方法執行結束之前永遠不會被垃圾收集。(不使用 java.lang.ref.WeakReference 和 SoftReference。)他們是垃圾收集的嗎?還是從不?編譯器對這類東西有優化嗎?(如果它們從不被垃圾回收,這意味著在執行需要很長時間的大方法時,可能需要將 null 分配給不再使用的變量。)
查看完整描述

2 回答

?
幕布斯6054654

TA貢獻1876條經驗 獲得超7個贊

正如Java 是否在對象仍在范圍內時可以完成對象中所闡述的那樣?,局部變量不會阻止引用對象的垃圾收集?;蛘?,正如這個答案所說,范圍只是一個語言概念,與垃圾收集器無關。

我將再次引用規范的相關部分JLS §12.6.1

可達對象是可以從任何活動線程的任何潛在持續計算中訪問的任何對象。

此外,我將答案的示例擴展到

class A {

    static volatile boolean finalized;


    Object b = new Object() {

        @Override protected void finalize() {

            System.out.println(this + " was finalized!");

            finalized = true;

        }

        @Override public String toString() {

            return  "B@"+Integer.toHexString(hashCode());

        }

    };

    @Override protected void finalize() {

        System.out.println(this + " was finalized!");

    }


    @Override public String toString() {

        return super.toString() + " with "+b;

    }


    public static void main(String[] args) {

        A a = new A();

        System.out.println("Created " + a);

        for(int i = 0; !finalized; i++) {

            if (i % 1_000_000 == 0)

                System.gc();

        }

        System.out.println("finalized");

    }

}

Created A@59a6e353 with B@6aaa5eb0

B@6aaa5eb0 was finalized!

finalized

A@59a6e353 with B@6aaa5eb0 was finalized!

這表明即使是變量在范圍內的方法也可以檢測到引用對象的終結。此外,從堆變量中引用也不一定會阻止垃圾收集,因為B對象不可訪問,因為當包含引用的對象也不可訪問時,沒有繼續計算可以訪問它。


值得強調的是,即使使用對象并不總是會阻止其垃圾回收。重要的是,正在進行的操作是否需要對象的內存,而不是每次訪問源代碼中的對象字段都必須在運行時導致實際的內存訪問。該規范指出:


可以設計優化程序的轉換,將可到達的對象的數量減少到比那些天真地認為是可到達的要少。[…]


如果對象字段中的值存儲在寄存器中,則會出現另一個示例。然后程序可能會訪問寄存器而不是對象,并且永遠不會再次訪問對象。這意味著該對象是垃圾。


這不僅僅是一個理論上的選擇。正如在 Java 8 中調用強可達對象的 finalize() 中所討論的,它甚至可能在對象上調用方法時發生,或者換句話說,this當實例方法仍在執行時,引用可能會被垃圾收集。


防止對象垃圾回收的唯一方法是,如果終結器也對對象進行同步,則對對象進行同步,或者調用Reference.reachabilityFence(object)Java 9 中添加的方法。柵欄方法的后期添加展示了優化器獲取的影響在早于想要的垃圾收集問題上,從版本到版本更好。當然,首選的解決方案是編寫完全不依賴于垃圾收集時間的代碼。


查看完整回答
反對 回復 2022-07-14
?
交互式愛情

TA貢獻1712條經驗 獲得超3個贊

并不是所有的對象都在堆空間中。但這通常是正確的。Java 已擴展為具有堆棧本地對象,前提是 JVM 可以檢測到該對象將僅與堆棧幀一樣長。

現在對于堆上的對象,它們在方法中具有本地引用。在處理方法時,與方法運行關聯的堆棧幀包含局部變量引用。只要可以使用引用(包括仍在堆棧幀中),對象就不會被垃圾收集。

一旦引用被銷毀,并且正在運行的程序無法再訪問該對象(因為沒有可以訪問它的引用),那么垃圾收集器將收集它。


查看完整回答
反對 回復 2022-07-14
  • 2 回答
  • 0 關注
  • 112 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號