簡體   English   中英

我已經“修復”了內存泄漏,但是......如何以更好的方式修復它?

[英]I've “fixed” a memory leak, but.. how to fix it in a better way?

這是一個非常快速和臨時的錯誤修復..它有效,但我想找到一個更好的理解和解決方案。

這是生成泄漏的類構造函數

final transient  DataInputStream din;
final transient  DataOutputStream dout;
final transient  BufferedReader bin;
final transient  BufferedWriter bout;

NData(Socket sock0) throws IOException
    {
        sock=sock0;
        din= new DataInputStream(sock.getInputStream());
        dout = new DataOutputStream(sock.getOutputStream());
        bin = new BufferedReader(new InputStreamReader(din));
        bout = new BufferedWriter(new OutputStreamWriter(dout));
     //   .. 
    }

錯誤修復是更改它(刪除最終),以便讓我稍后分配null

transient  DataInputStream din;
transient  DataOutputStream dout;
transient  BufferedReader bin;
transient  BufferedWriter bout;

NData(Socket sock0) throws IOException
    {
        sock=sock0;
        din= new DataInputStream(sock.getInputStream());
        dout = new DataOutputStream(sock.getOutputStream());
        bin = new BufferedReader(new InputStreamReader(din));
        bout = new BufferedWriter(new OutputStreamWriter(dout));
     //   .. 
    } 

 //And to add a "magic" destructor

 void nuller() {
        din=null;
        dout=null;
        bin=null;
        bout=null;
    }

有一個finish方法結束了線程,關閉了流,所以我添加了“nuller”方法調用,內存泄漏消失了。

為什么在完成線程並關閉流后,它會繼續在“byte []”中分配內存? 為什么GC不扔掉它? (除了那些帶有空對齊的臟之外)

編輯:

正如卡薩布蘭卡所說也許NData對象仍然存在,有一個

final static ConcurrentHashMap <String,NData>(); 

因此,將NData作為值,使用remove(key)從Map中清除對象,但是......似乎還不夠。

從HashMap中刪除唯一的對象引用是不足以刪除對象?

為什么在完成線程並關閉流后,它會繼續在“byte []”中分配內存? 為什么GC不扔掉它?

只有在沒有對該對象的引用時,GC才會“扔掉”某些內容。 在您的情況下,這意味着某些東西仍然持有對NData對象的引用。 通過手動調用你的nuller方法,你只需釋放對成員變量的引用( dindout等),但NData對象可能仍然存在。 您需要查看其他地方以找出誰正在使用此對象並確保清除此引用。

更新:您究竟是如何得出內存泄漏的結論? GC僅定期運行,因此不保證立即釋放對象。 您可以嘗試調用System.gc()來強制運行GC。 此外, ConcurrentHashMap (我不熟悉)可能是緩存並發的引用,並且可能在調用remove后不會立即釋放它們。

清理NData對象后,應該進行堆轉儲。 然后在堆中找到NData對象(因為從你的描述中,有人仍然持有它的強引用!)。 然后找到該對象如何從根集到達。

最近我不得不這樣做,我發現這個過程很方便:

VisualVM ,用於進行堆轉儲。

Eclipse Memory Analyzer (我單獨使用它)來分析堆,特別是從根集中查找路徑。

第二個當前比第一個更先進,但第一個的GUI非常好用(如果它也是功能完整的!)。

在你的空調中,調用bin.close()和bout.close()就可以了。 只需確保在某個地方的finally塊中調用nuller,以便始終調用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM