我有一个在我的Ubuntu 10.04机器上运行的Java程序,在没有任何用户交互的情况下,反复查询MySQL数据库,然后根据从DB读取的数据构造img和txt文件 . 它可以进行数万次查询并创建数万个文件 .
运行几个小时后,我的机器上的可用内存(包括交换空间)已经完全耗尽 . 我还没有启动其他程序,并且在后台运行的进程不会消耗太多内存,也不会真正增加消耗 .
为了找出分配如此多内存的内容,我想分析一个堆转储,所以我用-Xms64m -Xmx128m -XX:HeapDumpOnOutOfMemoryError启动了这个过程 .
令我惊讶的是,情况与以前一样,在几个小时之后,程序正在分配所有的交换,这超出了给定的最大值128米 .
用VisualVM调试的另一个运行显示堆分配永远不会超过最大128m - 当分配的内存接近最大值时,它的很大一部分再次释放(我假设是垃圾收集器) .
因此,稳定增长的堆不会成为问题 .
当内存全部耗尽时:
免费显示以下内容:
total used free shared buffers cached
Mem: 2060180 2004860 55320 0 848 1042908
-/+ buffers/cache: 961104 1099076
Swap: 3227640 3227640 0
top显示以下内容:
USER VIRT RES SHR COMMAND
[my_id] 504m 171m 4520 java
[my_id] 371m 162m 4368 java
(到目前为止,两个“最大”进程和唯一运行的java进程)
我的第一个问题是:
如何在操作系统级别(例如使用命令行工具)找到分配如此多内存的内容? top / htop没有帮助我 . 在许多情况下,许多相同类型的微小进程占用了内存:有没有办法智能地总结类似的进程? (我知道这可能不是主题,因为它是Linux / Ubuntu问题,但我的主要问题可能仍然是与Java相关)
我的老问题是:
为什么顶部输出中没有给出程序的内存消耗?
如何找出分配如此多内存的内容?
如果堆没有't the problem, is the only 2901164 the stack? (the stack shouldn'是一个问题,因为没有深"method call depth")
外部资源作为数据库连接怎么样?