2016-02-28 63 views
1

我目前對一個沒有調用finalize()方法的類的對象存在問題,儘管只存儲在作爲值的ConcurrentHashMap中,而對象的UUID作爲鍵地圖。儘管WeakReference沒有調用finalize()方法

這裏是我創建了一個例子(它不是在我的實際項目中使用的一個,但這個例子中也沒有調用的對象finalize()方法。

TestMain.class //主類處理HashMap中

public class TestMain { 

public static ConcurrentHashMap<String, WeakReference<Test>> map = new ConcurrentHashMap<String, WeakReference<Test>>(); 

    public static void main(String args[]) { 
    map.put("Key1", new WeakReference<Test>(new Test("test 1", 2))); //This "Test" Object shouldn't be accessible anywhere besides the HashMap anymore, and therefore I want it to be "finalized" by the garbage collector. 
    System.out.println("DONE"); 
    } 
} 

的Test.class //對象類

public class Test { 
    public String string; 

    public int intt; 

    public Test(String string, int intt) { 
    this.string = string; 
    this.intt = intt; 
    } 

    @Override 
    protected void finalize() throws Throwable { 
    System.out.println("FINALIZED TEST CLASS: " + string); 
    super.finalize(); 
    } 
} 

當運行的主要方法,所有的被印刷爲 「DONE」 時我人口會d「FINALIZED TEST CLASS:Test 1」也可以在此之前打印。我的代碼有什麼問題,或者我誤解finalize()的工作原理?

另外,我想這個工作,我解釋一下,因爲我需要與finalize()方法的對象從「地圖」 Map從記憶中抹去一樣會有我的項目運行過程中產生的對象的幾百持續時間,所以我希望不再使用的對象被清除,爲更多新對象騰出空間。

編輯:我看到互聯網上的其他地方,人們說程序可能在垃圾回收器有機會處理上述對象之前終止。因此,我試圖通過添加一個簡單的while(true){}循環來讓我的程序不終止,並等待了幾分鐘,但仍然沒有看到該對象正在「完成」的消息。

任何幫助非常感謝,謝謝。

+4

無法保證finalize方法將被稱爲 – Pragnani

+0

@PragnaniKinnera那麼,我將如何手動處理這些對象後,他們不能在其他地方訪問?我現在很困惑 –

+1

@C_Beth這不是你的工作,GC會照顧到這一點。當你嘗試自己做這件事會引起額外的煩惱 – Pragnani

回答

1

正如在評論中提到的那樣,不能保證調用finalize方法。

Java編程語言不能保證哪個線程將 調用任何給定對象的finalize方法。但是,保證, 然而,當調用finalize時,調用finalize的線程將不會保留任何 用戶可見的同步鎖。如果finalize方法引發了 未捕獲的異常,則忽略 異常,並終止該對象的終止。

現在回來到您的他們不再訪問後這些對象手動配置的關注,你不需要搞定,Java垃圾收集器會處理,對於你與它的自動內存管理。如果你想加快垃圾收集,請閱讀G1垃圾收集器。

+0

好的謝謝;我不知道GC只會在需要時自動運行。 –

3

最可能的解釋是GC從未跑過。

  • 如果GC沒有運行,那麼對象不會被垃圾收集。

  • 如果沒有收集到對象,它們將不會被最終確定。

試圖讓我的程序不是通過把一個簡單而(真){}循環終止並等待一兩分鐘,

等待GC不會幫幫我。通常它只在需要運行< <時運行;即,當其中一個堆空間超過充滿閾值時。

您可以通過調用System.gc()來強制GC運行...但是這是不良做法。它會使您的應用程序效率低下且無法響應。

嘗試在終結器中做任何事情都是不明智的,必須及時完成。您應該設計自己的代碼,以便:

  • 它不一樣,如果一個對象從來沒有得到所有定稿無所謂了,
  • 也不要緊,當一個對象被敲定。

爲什麼?因爲你幾乎無法控制什麼時候對象被完成......而且如果你不打電話給System.gc() ......你根本不應該這樣做;往上看。

實際上,終結器是Java的一個特性,應該很少使用,如果有的話。唯一有效的用例涉及釋放與應用程序尚未整理的資源對象相關的外部資源。即使如此,應用程序最好使用「嘗試使用資源」(或finally塊)來明確清理資源。

+0

http://prntscr.com/a8w7rq添加了'System.gc()',它證明當GC被調用時它將全部正常工作。謝謝 –

相關問題