我们正在使用 Java 1.6(OpenJDK 和 Oracle JDK)在 Linux 上运行一个应用程序。 JVM 本身有最大 3.5 GB 堆和 512 MB permgen 空间。然而,运行一段时间后,top
报告该进程正在使用大约 8 GB 的虚拟内存,而 smem -s swap p
报告大约有 3.5 GB 被交换。
在一台服务器上运行数千个图像文件的更大导入后,几乎没有交换空间,并且由于操作系统未能为这些应用程序分配内存,对 native 应用程序的调用(在我们的例子中是 Im4java 调用 Image Magick)失败.
在另一种情况下,交换空间在数周内填满,导致操作系统因交换空间不足而杀死 JVM。
我知道 JVM 需要超过 4 GB 的内存用于堆(最大 3.5 GB)、permgen(最大 512 MB)、代码缓存、加载的库、JNI 框架等。
我遇到的问题是如何找出实际使用了多少内存。如果 JVM 堆内存不足,我会得到一个可以分析的转储,但在我们的例子中,操作系统内存被耗尽,因此 JVM 不会生成转储。
我知道 JRockit 有 jrcmd
,但不幸的是我们不能只切换 JVM。
似乎还有一些库可以跟踪 native 内存使用情况,但其中大多数库似乎需要重新编译 native 代码 - 除了 Im4java(AFAIK 只运行 native 进程,我们不使用 DLL/SO-此处集成)和 JVM,据我们所知,不涉及其他 native 代码。
除此之外,我们不能使用可能对性能或稳定性产生巨大影响的库/工具来长期(数周)跟踪生产系统上的内存使用情况。
所以问题是:
我们如何获得有关 JVM 实际需要所有内存的信息,最好是一些详细信息?
最佳答案
在 JVM 中替换内存分配器(jemalloc 或 tcmalloc)时,您可能会发现对“zlib/gzip”(自 Java 7 起的 pdf 处理或 http 编码)、“java2d”或“jai”的引用。
但要真正诊断 native 内存泄漏,需要 JIT 代码符号映射和 Linux 最近的分析工具:perf
、perf-map-agent
和 bcc
.
详见相关回答https://stackoverflow.com/a/52767721/737790
非常感谢Brendan Gregg
关于java - 分析/追踪 JVM 中潜在的 native 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26343377/