【发布时间】:2014-12-08 05:13:51
【问题描述】:
我们正在使用 Java 1.6(OpenJDK 和 Oracle JDK)在 Linux 上运行应用程序。 JVM 本身最大有 3.5 GB 堆和 512 MB permgen 空间。但是,运行一段时间后,top 报告该进程正在使用大约 8 GB 的虚拟内存,smem -s swap p 报告大约有 3.5 GB 被交换。
在一台服务器上大量导入数千个图像文件后,几乎没有剩余交换空间,并且由于操作系统未能为这些应用程序分配内存,调用本机应用程序(在我们的例子中 Im4java 调用 Image Magick)失败.
在另一种情况下,交换空间在几周内被填满,导致操作系统因交换空间不足而杀死 JVM。
我了解 JVM 将需要超过 4 GB 的内存用于堆(最大 3.5 GB)、permgen(最大 512 MB)、代码缓存、加载的库、JNI 帧等。
我遇到的问题是如何找出实际使用了多少内存。如果 JVM 堆内存不足,我会得到一个可以分析的转储,但在我们的例子中,是操作系统内存被耗尽,因此 JVM 不会生成转储。
我知道 JRockit 有 jrcmd,但不幸的是我们不能只切换 JVM。
似乎还有几个库可以跟踪本机内存使用情况,但其中大多数似乎需要重新编译本机代码 - 除了 Im4java(AFAIK 仅运行本机进程,我们不使用 DLL/SO-在这里集成)并且 JVM 没有涉及我们所知道的其他本机代码。
除此之外,我们不能使用可能对性能或稳定性产生巨大影响的库/工具来长期(数周)跟踪生产系统上的内存使用情况。
所以问题是:
我们如何才能获得有关 JVM 实际需要所有内存的信息,最好是一些详细信息?
【问题讨论】:
-
再次检查。看起来像调用了一些本机方法。以及从本机调用中获取的内存。
-
@talex 好吧,我知道我们的应用程序使用的唯一本机代码是 Im4java,它声明它使用
ProcessBuilder。我们还在 JBoss 7.2 上运行,它也可能使用本机代码,但在没有进一步信息的情况下猜测其中的任何部分或哪一个是罪魁祸首,恕我直言,这是一项毫无意义的任务。因此,提供该信息的工具的问题是,以便我们能够追踪导致内存泄漏的本机方法。
标签: java linux memory memory-leaks