2011-01-13 43 views
4

我在下午7:41採用Java堆轉儲,我正在使用Eclipse內存分析工具進行分析。堆轉儲包含20個會話對象。堆轉儲中不可能的Java內存引用

在堆中的這些會話對象之一上使用GC根路徑命令顯示以下3個會話對象的引用。

  • 來自Finalizer線程擁有的「未終止」鏈接列表的終結器引用。我的對象是第三行定稿。
  • 從消息處理程序線程強烈引用會話對象,該線程本身是從計劃在晚上7:11運行的清理TimerTask引用的。
  • 對WeakHashMap $ Entry中會話對象的弱引用。 WeakHashMap由一個靜態強參考保持活着。

如果會話對象仍然存在強和弱引用,它們如何處於終結器隊列中?

其餘19個會話對象中,還有1個在終結器隊列中,並且具有類似的弱引用。所有其他18個會話對象僅被弱引用。 GC爲什麼沒有清除這些虛弱的參考?

幾個基本點:後的弱裁判已被清除

  • 對象只能享有定稿(http://download.oracle.com/javase/6/docs/api/java/lang /ref/package-summary.html)
  • 會話對象沒有一個終結器,它可能會重新生成它,即使它已經在對象仍然處於其他對象後面的未終止隊列中時不能運行。
  • 我的應用程序沒有使用Phantom refs,這是唯一一個對象有資格完成時應該能夠存在的引用。即使我的應用程序確實使用幻影參考,這些對象也不會將其對象所在的對象引用。
+1

你是否確實有一個會話對象在它仍然可達時完成了?如果沒有,那麼我不會擔心它。排隊等候並不一定意味着它將被定稿,而強大的和/或弱的參考文獻仍然存在。 – finnw 2011-01-13 12:52:02

+0

什麼機制可以阻止終結器隊列中的對象被終結?如果對象不符合條件,則這些對象不應位於此隊列中。 – mchr 2011-01-13 13:22:11

+0

這在[Cowan的答案]中解釋過(http://stackoverflow.com/questions/4680081/impossible-java-memory-references-in-heap-dump/4759026#4759026)。 – finnw 2011-01-21 14:13:38

回答

10

我認爲你正在做這裏的錯誤是在這一部分:

從終結器線程擁有的「未終結」鏈表終結參考。我的對象是第三行定稿。

如果你談論的是這樣的:

static private Finalizer unfinalized = null; 
Sun的 Finalizer.java

(一Finalizer包含nextprevFinalizer,因此 '鏈表' 的一部分,對於那些沿在家玩)那麼這不是要完成的事情清單。

Finalizer.add()不是(因爲我認爲你假設)在最終確定過程中調用時,當對象無法訪問;相反,在創建對象的時間處調用該方法(例如在<init>期間,通過本機代碼,對於覆蓋finalize()的任何對象)。

next鏈中存在終結器並不意味着它即將完成;它是

static private ReferenceQueue queue 

它擁有這樣的對象。正在鏈接列表中意味着它有 a finalize()方法。因此,你的第一點是紅鯡魚,這是你保持物品可到達的第二點,第三點從第二點流出(因爲在對象可到達時不會清除WeakReference)。

希望這會有所幫助!

0

弱引用僅表示GC。當它被清除時,你沒有硬性保證。

0

您可以使對象計劃再次可用。

我知道:

對話對象不 沒有終結這可能 復活它,即使它是 已經不能運行,而 對象仍處於未確定 排在其他對象後面。

然而,可能有其他的對象這樣做(即有參考會議,讓自己rez'd)。無論哪種方式顯示該會議thingie的終結者。

注意:在清除幻影參考之前,對象不可用於最終化。 (幻影參考最常用於安排驗前處理清理操作,javadoc),pre(不會像弱者那樣發佈)。