2010-01-08 138 views
6

我有一個正在運行的java webapp,我用visualVM監視可能的內存泄漏?

這裏的堆的圖表:

heap http://www.freeimagehosting.net/uploads/9bb3841450.png

的用兩套請求,一個在3:20,另一個在4:40 aprox的測試(它們在圖中所表示唯一的兩個峯值)。

我的問題是:這是否意味着我有內存泄漏?我擔心中間部分,雖然GC運行,但堆始終保持在250MB。

非常感謝您的見解。

+1

樣本大小爲2並不能提供足夠的信息來聲明泄漏。是的,可以隱藏在該圖中:右側的分配大小大於左側的分配大小。或者,可以像* binil *提到的那樣,只是有些物體被提升到了終身代,而你沒有一個主要的GC。 – kdgregory

+0

真的,確定是否有泄漏的唯一方法是比較一段時間內保留的活動對象的數量。我發佈了一篇關於如何分析堆轉儲的文章(這裏)(http://www.kdgregory.com/index.php?page=java.outOfMemory)。 – kdgregory

回答

5

在3:20的第一個請求導致了一些內存被保留,但注意到第二個請求後的GC回收了大部分內存。我也認爲主要的氣相色譜是在4:40的第二次請求後才執行的。

看起來沒有泄漏。我的理論是,在3:20的請求導致年輕一代填滿,而由此產生的小型GC向一些老一代推銷了一些東西。下一個主要的GC由於4:40的請求而導致大部分問題得到了解決。

您可以通過使用一個分析器在3:20發出的一個同樣的請求之前,以紀念堆,迫使一個完整的GC,然後檢查哪些對象揮之不去驗證這一點。我不確定VisualVM是否允許您(1)標記堆並(2)強制執行完整的GC,但OptimizeIt曾經這樣做。

+0

非常感謝。你能指出一個很好的參考文件來追蹤所有這些概念嗎? (年輕一代,老一代,不同類型的GC運行等) –

+1

http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html可能會幫助 –

+0

事實上,使用'visualGC'插件顯示對象被提升到堆的另一部分。 –

0

你是說在3:20之前沒有請求嗎?如果是這樣,比我會說我沒有看到任何泄漏的證據。

我不知道你的應用程序,但是對於一些在第一次使用該應用程序時初始化JVM的生命週期的對象而言,它是典型的(基於體系結構/設計)。

0

您使用的是什麼JRE?堆/ GC相關參數傳遞給應用程序?

峯值並不差(如果服務器有更多的待辦事項,則意味着峯值增加)。但是看起來不太好,以至於4:40之後的水平(當負載再次降低時)隨着負載之前的水平上升而升高。不過,這並不需要是...

現在你應該看看更詳細,哪些對象或對象的圖形都保存在堆中。所以,做同樣的測試再次運行,包括(與分析器):

  • 負載離開前達
  • 負載下山後(一定要做好手動GC觸發)採取堆快照採取堆快照

現在你應該分析差異和你是否看到奇怪的對象,應該已經被垃圾清理。

0

JvisualVM允許你強制垃圾收集。

嘗試使用,看看會發生什麼。

+0

它實際上強制它,還是它調用System.gc()? –

+0

我相信它會強制它。也許它只是Sun JVM。 –

+0

它實際上調用'System.gc()'它不強制任何東西。 –

-1

這是什麼意思,內存泄漏?我認爲像SUN這樣的JVM實現並不會有這樣一個瘋狂的bug。當你沒有參考內存位置(殭屍)或者你沒有任何回收它的可能性時,理想地使用內存泄漏字。如果您在編程過程中遇到了錯誤的編程習慣,那麼您不得不引用不再使用的對象,並且它們在更大的範圍內(使用壽命),則會消耗更多的內存,而不會讓GC選擇重新採集它。