2010-05-18 34 views
18

有效的Java說:如何避免回調中的內存泄漏?

的存儲器中的第三個常見的來源漏 是聽衆和其他的回調。如果 您實現了一個API,其中客戶端 註冊回調但不 註銷它們明確,他們將 積累,除非你採取一些 行動。確保 回調是垃圾回收 的最好方法是僅存儲對它們的引用(例如, ),僅將它們僅存儲爲 WeakHashMap中的鍵。

我是Java的初學者。有人可以教我如何在回調中創建弱引用,並告訴我他們如何解決內存泄漏問題?謝謝。

回答

11

閱讀this文章

關鍵拿走的題是:

你可以認爲直接引用作爲不需要 額外的編碼來創建或訪問 對象 強引用。其餘三種類型的 引用是在 java.lang.ref包中找到的 引用類的子類。軟引用 由SoftReference 類提供,弱引用由 WeakReference類和phantom 引用由PhantomReference提供。

軟引用就像一個數據緩存。 當系統內存不足時,垃圾收集器可以任意釋放一個對象,其唯一引用是軟引用。換句話說,如果 對對象沒有強引用,則 該對象是 版本的候選對象。垃圾回收器是 ,在拋出 OutOfMemoryException之前釋放任何軟 引用。

弱引用弱於軟引用 。如果對象的引用僅爲 ,那麼 垃圾收集器可以隨時回收對象使用的內存。 有沒有要求低的內存情況。通常,該對象使用的內存 將在垃圾回收器的下一個回合中回收到 。

幻影參考文獻涉及清理 任務。他們在垃圾 收集程序執行完成程序 過程並釋放對象之前提供通知 。考慮 它是一種在 對象內執行清理任務的方法。

其次是WeakListModel列表,我不會發布以避免混淆此響應。

+0

我只是想指出,鏈接斷開 – Maurice 2015-06-04 00:51:31

+0

固定的,謝謝。 – 2015-06-04 00:54:01

+1

哇快點!謝謝 – Maurice 2015-06-04 00:54:54

8

爲了說明一個快速的(粗)例如概念,考慮以下因素:

public interface ChangeHandler { 
    public void handleChange(); 
} 

public class FileMonitor { 

    private File file; 
    private Set<ChangeHandler> handlers = new HashSet<ChangeHandler>(); 

    public FileMonitor(File file) { 
     this.file = file; 
    } 

    public void registerChangeHandler(ChangeHandler handler) { 
     this.handlers.add(handler); 
    } 

    public void unregisterChangeHandler(ChangeHandler handler) { 
     this.handlers.remove(handler); 
    } 

    ... 
} 

如果一個客戶端類,然後使用這個FileMonitor API,他們可能做到這一點:

public class MyClass { 

    File myFile = new File(...); 
      FileMonitor monitor = new FileMonitor(myFile); 

    public void something() { 
     ... 
     ChangeHandler myHandler = getChangeHandler(); 
     monitor.registerChangeHandler(myHandler); 
     ... 
    } 
} 

如果MyClass的作者隨後忘記在與處理程序一起完成時調用unregisterChangeHandler()FileMonitorHashSet將永久引用已註冊的實例,導致它保留在內存中直到FileMonitor被銷燬或應用程序退出。

爲了防止這種情況發生,Bloch建議使用弱引用集合而不是HashSet,這樣如果您的MyClass實例被銷燬,引用將從監視器的集合中刪除。

你可能有WeakHashMap替換FileMonitorHashSet,並使用處理器作爲關鍵,因爲當該對象的所有其他引用都消失後會自動從集合中刪除的處理程序。

+1

謝謝你的例子,但我還是不太明白。當something()返回時,強引用myHandler將超出範圍。是不是因此WeakHashMap引用的處理程序隨時可以被銷燬(即使MyClass實例仍然存在)?那不是你想要的嗎? – kodu 2016-09-02 12:58:36

+0

啊,我開始看到......你可以使用WeakHashMap ,那麼這個鍵實際上就是MyClass的實例。 – kodu 2016-09-02 13:07:32

+0

我認爲myHandler應該在something()返回之後,即使MyClass實例仍然存在。所以WeakHashMap 優於WeakHashMap yuxh 2018-02-01 03:53:15