我有一个运行在我的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