我有一個運行在我的Ubuntu 10.04機器上的Java程序,並且在沒有任何用戶交互的情況下反覆查詢MySQL數據庫,然後根據從數據庫中讀取的數據構造img和txt文件D B。它使數以萬計的查詢和創建數以萬計的文件。Java程序的內存消耗問題
經過幾個小時的運行後,我的機器上的可用內存(包括交換空間)完全用完。我還沒有開始其他程序,並且在後臺運行的進程不會消耗太多內存,並且不會真正增加消耗。
爲了找出分配這麼多內存的內容,我想分析一個堆轉儲,所以我使用-Xms64m -Xmx128m -XX:+ HeapDumpOnOutOfMemoryError啓動了該進程。
令我驚訝的是,情況和之前一樣,幾個小時後程序分配了所有交換,超過了給定的最大值128m。
用VisualVM調試的另一個運行表明,堆的分配永遠不會超過128M的最大值 - 當分配內存接近最大值時,它的很大一部分會再次釋放(我假設垃圾回收器)。
因此,它不會成爲一個穩步增長的問題堆。
當存儲器被全部用完:
免費顯示以下內容:
total used free shared buffers cached
Mem: 2060180 2004860 55320 0 848 1042908
-/+ buffers/cache: 961104 1099076
Swap: 3227640 3227640 0
頂部示出了以下內容:
USER VIRT RES SHR COMMAND
[my_id] 504m 171m 4520 java
[my_id] 371m 162m 4368 java
(迄今爲止兩個 「最大」 的過程和唯一的java進程運行)
我的第一個問題是:
- 我該如何找到操作系統級別(例如,與命令行工具)什麼是分配這麼多的內存? top/htop沒有幫助我。在很多情況下,許多相同類型的微小進程會消耗內存:是否有智能地總結類似進程的方法? (我知道這可能是題外話,因爲它是一個Linux/Ubuntu的問題,但我的主要問題仍可能與Java相關的)
我的老問題是:
- 爲什麼不是在頂部輸出中給出的程序的內存消耗?
- 如何找出分配如此之多的內存?
- 如果堆不是問題,是堆棧中唯一的「分配因子」? ( 堆棧不應該是一個問題,因爲沒有深度的「方法調用深度」)
- 作爲數據庫連接的外部資源如何?
嘗試使用性能分析工具:http://stackoverflow.com/a/9205812/90909 – qrtt1 2012-03-03 13:31:32
@ qrtt1:我使用了VisualVM,但是這表明堆不是問題(參見上文)。 – 2012-03-03 13:40:42
您可以在這裏找到答案,我認爲http://stackoverflow.com/a/9306054/1140748和http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_oom(請參閱錯誤說明) – 2012-03-03 13:43:01