2012-12-06 14 views
2

我知道session.invalidate()發佈httpsession。但是當我監視容器內存時,它不會下降。以下是我觀察 -簡單的方法從Java Web應用程序的內存中清理無效的會話

  • 登錄(我的應用程序創建一個會話)
  • 用戶執行某些活動,增加進程的內存。
  • 註銷。 (註銷控制器明確地使會話無效)
  • 監視進程內存。它永遠不會下降。

最初我以爲,垃圾收集可能只有在達到低內存可用狀態後才能工作。爲了證實這一點,我使用-Xmx來減少內存。但仍然是同樣的錯誤。事實上,當我使用單獨的瀏覽器進行相同的活動時,我看到了OOM錯誤。

這裏有什麼遺漏嗎?

+0

它可能不是實際上是已佔用的堆空間的會話數據。考慮使用「jmap -dump:file =/tmp/heap.hprof 」來獲取進程堆的快照,然後使用像Eclipse MAT這樣的工具來查看實際內容。 – GargantuChet

+0

我嘗試了這一點,並確定在轉儲分析後,內存中的數據是用戶在登錄時執行的過程。 – user1401472

+0

Eclipse MAT還可以告訴您哪些對象負責在內存中保留特定對象。 「Dominator」報告對此很有幫助 - 如果存在仍然保存數據的線索或對象,則可以使用支配者信息來確定它是什麼。我意識到這不是很具體,但除非有什麼被破壞,容器不應該保留舊的會話數據。有機會有另一個對象持有參考。 – GargantuChet

回答

1

它會在內存中,直到垃圾收集器運行並找到未引用的對象並清除它們。您可以嘗試在session.invalidate()之後使用System.gc()明確調用GC,僅用於測試目的。也調用System.gc()不需要調用GC,因爲jvm會做出是否運行GC的決定。

+0

但請記住,System.gc()會強制執行非常昂貴的垃圾收集循環,從而導致JVM在幾秒或更長時間內無響應,具體取決於總堆大小。系統將在適當的時候使用更便宜的GC方法,因此對用戶活動(例如會話失效)作出響應的顯式System.gc()幾乎總是一個壞主意。 – GargantuChet

+0

是的,它只是用於測試目的。 – Subin

+0

顯式System.gc將不是實時選項。我還探索了容器中的「垃圾收集間隔」設置。但各種論壇建議不要因爲相同的原因而減少太多。 – user1401472

1

你可以嘗試以下操作之一來分析問題:

  1. 打印GC日誌,看看有多少年輕/全GC集合發生:

    -XX:+ UnlockDiagnosticVMOptions -XX:+ LogVMOutput -XX:日誌文件= jvm.log -XX:+ HeapDumpOnOutOfMemoryError -Xloggc:BIN/gc.log -XX:+ PrintGCTimeStamps -XX:+ PrintGCDetails -verbose:GC

  2. 檢查類別直方圖以查看全部GC是否收集了您的類的實例。比較完整GC之前/之後的實例數量。啓用:

    -XX:+ PrintClassHistogramBeforeFullGC -XX:+ PrintClassHistogramAfterFullGC

  3. 採取直方圖快照,再看看是否正在收集類:

    JMAP -histo $ PID

  4. 查看該類是否包含一個finalize()方法,該方法將阻止在GC期間收集的對象。

  5. 由於GargantuChet建議,收集HEAPDUMP,看看哪些對象正在引用您的類的實例。

+0

另外,「監視進程內存」是什麼意思?所用的進程內存不等於堆佔用。 GC可能有垃圾回收您的實例,這會影響堆用量,但可能在「進程內存大小」統計信息中不可見。 –

+0

感謝上面提到的所有要點。我會毫不猶豫地檢查他們。但是你說什麼在任務管理器中顯示的內存使用量不反映最新的內存統計信息?從我所看到的,我的應用程序恰好在任務管理器中的內存達到-Xmx內存時拋出OOM。 – user1401472

+0

我想你應該檢查GC日誌以查看堆中究竟發生了什麼。顯示JVM保留的內存總量的統計信息不一定需要反映Heap佔用情況。 VM可以例如預先保留所有頁面。此外,使用** - XX:+ HeapDumpOnOutOfMemoryError **查看哪些實例觸發OOM。 –

相關問題