Java 8 中可訪問物件的JVM 終結:探索
儘管遵循不鼓勵使用Finalize() 的最佳實踐,最近從Java 7 升級到Java 8 發現了一個意想不到的問題。在這種情況下,目前執行緒堆疊仍可強存取的物件將在 Java 8 執行時期中進行終結。
理解程式碼和異常
有問題的程式碼涉及自訂 MIME 庫,其中 MIMEBodyPart 類別擴展了 HTTPMessage。 HTTPMessage 實作了一個 Finalize() 方法,該方法嘗試關閉其關聯的輸入流,當流在活動 writePart() 操作期間已關閉時會導致異常。
調查原因
由於對意外的最終確定感到困惑,開發人員深入研究了程式碼和 JVM 行為。發現 MIMEBodyPart 物件確實可以從目前線程的堆疊訪問,因此不應該被最終確定。
假設無法存取的可能性
儘管如此儘管該物件明顯可達,但理論上Java 虛擬機(JVM) 仍然可以將其視為不可訪問如果後續程式碼中沒有明確引用。這種「不可達能力」的概念甚至擴展到堆疊上的活動方法呼叫。
示範不可達性的範例
為了說明此行為,提供了一個簡化的程式碼範例:
在此範例中,loop() 方法包含一個定期觸發垃圾回收的大規模循環。儘管循環方法主動呼叫 FinalizeThis 物件的實例方法,但由於該物件明顯不可達,JVM 仍會完成該物件並對其進行垃圾回收。
將假設應用到原始場景
據推測,MIMEBodyPart 物件可能會出現類似的情況。如果它儲存在局部變數中而沒有任何後續引用,則它可能會變得無法存取並容易被最終確定。
更新和其他觀察
透過進一步的測試和分析,很明顯,JIT 編譯器在這種行為中發揮了作用。透過強制方法在執行前進行 JIT 編譯(-Xcomp 選項),過早終結的問題再次出現。這表明簡化範例中最初缺乏最終確定是由於解釋而不是編譯,後者執行更積極的可達性分析。
結論
雖然問題的具體情況可能會因具體的程式碼結構和執行環境而異,但即使對於可到達的對象,由於感知到的不可達性,潛在最終確定的基本概念也值得注意。它強調了理解物件可及性以及活動對像上終結呼叫的潛在後果的重要性。
以上是為什麼可存取的 Java 物件在 Java 8 中最終確定,儘管最佳實踐不鼓勵「finalize()」?的詳細內容。更多資訊請關注PHP中文網其他相關文章!