我一直有這個內存泄漏問題幾天,我想我現在有一些線索。我的java進程的內存不斷增長,但堆不增加。我被告知,如果我創建多個線程,這是可能的,因爲Java線程使用堆外的內存。如何回收Java線程堆棧使用的內存?
我的java進程是一個服務器類型的程序,所以有1000-2000個線程。創建和刪除正在進行。我如何回收java線程使用的內存?我是否簡單地刪除對線程對象的所有引用並確保它已終止?
我一直有這個內存泄漏問題幾天,我想我現在有一些線索。我的java進程的內存不斷增長,但堆不增加。我被告知,如果我創建多個線程,這是可能的,因爲Java線程使用堆外的內存。如何回收Java線程堆棧使用的內存?
我的java進程是一個服務器類型的程序,所以有1000-2000個線程。創建和刪除正在進行。我如何回收java線程使用的內存?我是否簡單地刪除對線程對象的所有引用並確保它已終止?
是的。這就是答案。只要存在對任何Java對象的主動引用,那麼該對象在完成時不會被垃圾收集。 如果你正在創建和銷燬線程而不是將它們合併,我認爲你還有其他問題。
從Java API文檔線程死的時候:
所有線程都沒有守護線程已經死亡,要麼通過調用run方法返回或通過拋出一個傳播超越了run方法異常。
當他們從運行()方法返回時線程死亡。當他們死亡時,他們是垃圾收集的候選人。您應確保線程釋放對對象的所有引用並退出運行()方法。
我不認爲你的線程的nulling引用真的會訣竅。
您還應該查看Java 5及更高版本中的新線程工具。檢查API文檔here中的包java.util.concurrent。
我也推薦你去看書Concurrency in Practice。這對我來說是無價的。
「當它們死亡時,它們是垃圾收集的候選對象」,但前提是沒有其他對象仍然持有對這些死亡線程的引用。 – 2009-09-25 20:33:39
如果它們是守護線程呢? – erotsppa 2009-09-25 20:51:09
@erotsppa:守護進程線程相同。 – 2009-09-26 03:17:45
這是很多線程,每個線程強加一個內存開銷,以及用於管理它們的其他資源(上下文切換等)。使用分析器查看線程活動 - 您可能會發現大多數線程大多數時間處於空閒狀態。
我建議第一步是查看使用java.util.concurrent提供的線程池來管理線程。不是創建線程,而是創建交給池的任務。調整池,直到你有一個合理繁忙的線程數量少得多。這可能很好地解決了內存問題;它肯定會提高性能。
有兩件事情會導致線程不被垃圾收集。
任何仍處於活動狀態的線程都不會被垃圾收集。直到通過Thread.start()
調用的run
方法退出(正常或拋出異常),線程纔會處於活動狀態。一旦發生這種情況(並且線程的未捕獲的異常處理程序已完成),線程就已經死亡。
對線程的線程對象的任何實時引用都會阻止它被垃圾收集。實時引用可以在您的代碼中,或者如果您使用線程池,它們可以是池數據結構的一部分。
我java進程不斷增長,但尚未堆不增加的內存。
這將是因爲每個線程都有一個大的(例如1Mb)堆棧段,它並未在Java堆中分配。
當線程啓動線程的堆棧段只分配,並儘快線程終止釋放。這同樣適用於(我認爲)線程的線程局部映射。一個非「活着」的線程對象根本不佔用太多內存。
所以總結一下。您似乎有很多活動的線程。只要他們還活着,他們就不會被垃圾收集,而讓他們釋放記憶的唯一方法就是讓他們死......不知何故。
爲了減少內存使用,你需要做的一項或多項:
run()
方法等),以弄清楚他們爲什麼還在閒逛。
+1了聯合提。 – 2009-09-25 19:58:08