java - Java程序的内存消耗问题

标签 java memory

我有一个在我的 Ubuntu 10.04 机器上运行的 Java 程序,无需任何用户交互,重复查询 MySQL 数据库,然后根据从数据库读取的数据构造 img 和 txt 文件。它会进行数以万计的查询并创建数以万计的文件。

运行几个小时后,我机器上的可用内存(包括交换空间)已完全用完。我没有启动其他程序,后台运行的进程不会消耗太多内存,也不会真正增加消耗。

为了找出分配这么多内存的原因,我想分析一个堆转储,所以我用 -Xms64m -Xmx128m -XX:+HeapDumpOnOutOfMemoryError 开始了这个过程。

令我惊讶的是,情况和以前一样,几个小时后,程序分配了所有的交换空间,远远超出了给定的 128m 的最大值。

用 VisualVM 调试的另一次运行显示堆分配永远不会超过最大值 128m - 当分配的内存接近最大值时,它的很大一部分会再次释放(我假设是垃圾收集器)。

因此,稳定增长的堆不会成为问题。

当内存全部用完时:

free 显示如下:

             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 相关)

我的老问题是:

  • 为什么顶部输出中没有给出我的程序的内存消耗?
  • 如何找出分配这么多内存的原因?
  • 如果堆不是问题,那么唯一的“分配因素”是堆栈吗? (这 堆栈应该不是问题,因为没有很深的“方法调用深度”)
  • 作为数据库连接的外部资源呢?

最佳答案

如果您的 Java 进程确实是占用内存的进程,并且在 VisualVM 或内存转储中没有任何可疑之处,那么它必须位于 native 代码的某个位置 - 无论是在 JVM 中还是在您正在使用的某些库中。例如,在 JVM 级别上,如果您使用 NIO 或内存映射文件。如果您的某些库使用 native 调用,或者您的数据库使用的不是类型 4 的 JDBC 驱动程序,则可能存在泄漏。

一些建议:

  • 有一些细节如何在 native 代码中查找内存泄漏here .不错read也。
  • 像往常一样,确保您正确关闭了所有资源(文件、流、连接、线程等)。其中大多数在某些时候调用 native 实现,因此消耗的内存在 JVM 中可能不会直接可见
  • 检查操作系统级别消耗的资源 - 打开文件的数量、文件描述符、网络连接等。

关于java - Java程序的内存消耗问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9546449/

相关文章:

Java jax-ws 目录文件 : difference between PUBLIC and SYSTEM entries

c++ - 在c++中使用x64系统和x86应用程序分配大内存

memory - 了解 Rust 中的 Rc 内存泄漏

windows - 如果共享内存的进程之一被终止,共享内存会发生什么?

java - 奇怪的内存使用情况

c++ - 删除数组类型指针的元素导致错误?

java - 使用评级类实现赞成/反对评级

java - Eclipse (STS) 试图创建 appfuse-basic-jsf :RELEASE fails

java正则表达式括号

java - 从上到下理解 JVM 中的 Java 代码生命周期