2011-09-30 82 views
3

我爲生產團隊編寫了一個應用程序來衡量他們的分數,它運行良好2-3周,然後運行副本的機器減速並重新啓動修復它。如何查找Java應用程序中的內存泄漏?

解決此問題的最佳實踐步驟是什麼?

+0

你是什麼意思「的機器......減慢」?你正在重啓物理服務器還是java進程? – jtoberon

+0

得到一個調試器/分析器,顯示內存使用情況等 –

+2

在這裏檢查http://olex.openlogic.com/wazi/2009/how-to-fix-memory-leaks-in-java/ –

回答

4

您需要分析堆並找出哪些對象被保留在那裏不應該。

一個選項:

嘗試減少-Xmx最大堆大小,以加快內存不足異常,在啓動時-XX:+HeapDumpOnOutOfMemoryError將此選項添加到JVM和然後加載生成到像Eclipse Memory Analyzer堆轉儲。

另一種選擇:

使用JMAP從正在運行的進程轉儲堆(可能需要sudo的權限)

jmap -heap:format=b <pid> 

,並再次,堆轉儲二進制加載到與jHat或者Eclipse內存分析器。

如果您的應用程序正在減速但未拋出OutOfMemoryError,那麼很可能您沒有泄漏,但您確實需要做一些JVM tuning,因爲它花費了太多的時間來處理GC。

你應該監控GC收集時間(你可以使用-Xloggc:/tmp/gc.out記錄它們),也可以使用jstat看到GC的頻率發生,並需要多長時間。

如果你有一個擁有大量中等壽命物體的應用程序,是年輕一代足夠大(-XX:NewRatio=N)?如果不是你的應用程序將花費很長時間將對象推廣到舊版本中,只能在不久之後對其進行GC處理(舊版本的GC相對於新一代而言相對昂貴,尤其是當您的內存已經分散時)。

此外 - 你有沒有啓用CMS收藏家?如果你有多核機器,我建議你這樣做(-XX:+UseConcMarkSweepGC)。

2

除非使用JNI,否則傳統意義上Java中沒有內存泄漏。

Java中的內存泄漏通常是指創建您不再使用的引用對象。症狀通常是應用程序的內存使用量不斷增加。你看到內存使用量增長嗎?

如果您在Google中搜索完全相同的問題並按照鏈接進行操作,那麼您最好做好準備。

要解決的最佳實踐是通常使用Profiler來檢查您的分配。它也可以指向性能瓶頸不是由「內存泄漏」

+1

大量意外的內存使用情況可以發生在保留string.substring(a,b)的返回值時,當字符串最初由大字符數組支持時。 – Joel

+0

這是一個有趣的事實。我不認爲我使用子字符串,儘管在這個特定的應用程序中,你的意思是說有其他操作有類似的問題? – davidahines

+0

而且最近的例子是一張地圖,你一直在填寫密鑰,你永遠不會再看。例如,在基於Web的應用程序中,如果您將東西存儲在具有關鍵sessionid的地圖中,或者甚至更糟糕,則可以使用sessionid +:「+ ,以便您可以在會話期間查看它,然後當會話過期時,那些條目只是坐在那裏曾經.. –

1

您可以檢查JVM需要通過使用OS實用內存引起的,如任務管理器或top

您可以使用配置文件來檢查您的java代碼的內存,例如,Java VisualVM

請記住,Java使用垃圾回收,所以「內存泄漏」的唯一方法是通過持有對(很多)未使用對象的引用。 Josh Bloch's Effective Java項目6(消除陳舊對象引用)解釋了這些情況以及如何很好地防止它們。

您還可以使用其他方法來檢查這種「內存泄漏」,例如, static analysis and pluggable type systemsjvm memory options

1

跟蹤內存問題的一件好事是通過在啓動時向java添加以下命令啓用垃圾回收日誌記錄-verbose:gc-XX:+PrintGCDetails-XX:+PrintGCTimeStamps。然後,您可以分析垃圾回收器的行爲方式,即GC運行的頻率,垃圾回收器回收內存需要多長時間,回收的內存量以及應用程序的已用內存是否增加。

這裏的解釋GC日誌輸出的文檔: GC tuning guide for Java 6