2010-08-04 19 views
3

這是一個非常快速和臨時的錯誤修復。 它的工作,但我想找到一個更好的理解和解決方案。我已經「修復」了內存泄漏,但是..如何以更好的方式修復它?

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

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)); 
    // .. 
    } 

的bug修復是爲了改變它(除去最後),以便讓我來分配無效後

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; 
    } 

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

爲什麼在完成線程並關閉流之後,它會一直在「byte []」中分配內存? GC爲什麼不把它扔掉? (除了空asignment髒後)

編輯:

卡薩布蘭卡說也許NDATA對象仍然存在, 有一個

final static ConcurrentHashMap <String,NData>(); 

得有NDATA作爲值,刪除(鍵)完成從地圖清除對象,但..這似乎還不夠。

從HashMap中移除唯一的對象引用不足以移除該對象嗎?

+0

我改變了標題,讓更多的人可以理解你的問題。 Si quieres lo dejas como lo tenias。 :P – 2010-08-04 18:57:32

+0

@Sergio,我不想要「最好」的方式,只想知道更好的方法 – 2010-08-04 19:05:11

+0

垃圾收集器吸。 – someguy 2010-08-04 20:05:48

回答

4

爲什麼在完成線程並關閉流之後,它會一直在「byte []」中分配內存? GC爲什麼不把它扔掉?

只有在沒有更多引用該對象的情況下,GC纔會「拋出」某些東西。就你而言,這意味着某件事物仍然對NData對象有參考價值。通過手動調用您的nuller方法,您只需釋放對成員變量(din,dout等)的引用,但NData對象可能仍處於左右。您需要查看其他地方以找出誰正在使用此對象,並確保清除此引用。

更新:你究竟是如何得出結論認爲存在內存泄漏? GC只能定期運行,因此不保證立即釋放對象。您可以嘗試撥打System.gc()強制GC運行。另外,ConcurrentHashMap(我不熟悉)可能會緩存併發性引用,並且有可能在調用remove之後不會立即釋放這些引用。

+0

+1也許你是對的,對象是「仍然躺在」有一個ConcurrentHashMap ();將NData作爲值,我從Map中刪除(鍵)對象,但是..似乎還不夠? – 2010-08-04 19:39:34

+0

@Update,我在Netbeans分析器中看到它,如果我不使用「nuller」,服務器最終會失效,它與HashMap而不是ConcurrentHashMap一樣,所以這不是問題,我認爲「remove」是不是「刪除」,我甚至試圖在使用刪除之前將參數分配給null。像map.put(k,null),map.remove(k),但是崩潰無論如何.. – 2010-08-05 12:49:54

+0

我想你應該嘗試Dimitris解決方案,然後檢查堆。 – casablanca 2010-08-05 15:06:31

1

在你的nuller調用bin.close()和bout.close()這樣做。 只要確保nuller在某個地方的finally塊中被調用,所以它總是被調用。

3

清理NData對象後,您應該進行堆轉儲。然後在堆中找到NData對象(因爲從你的描述中,有人仍然持有強烈的參考!)。然後找到這個對象是如何從root set到達的。

最近,我不得不這樣做,我發現使用這些工具的過程中方便:

VisualVM,採取堆轉儲。

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

第二個目前比第一個先進得多,但第一個的GUI很好用(如果它也是功能完整的!)。

+0

+1可以幫助,我會搜索這個方向 – 2010-08-04 19:59:05