[英]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
方法,你只需釋放對成員變量的引用( din
, dout
等),但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.