我们正在使用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实际需要所有内存的信息,最好是获取一些详细信息?
答案 0 :(得分:1)
在JVM中替换内存分配器(jemalloc或tcmalloc)时,您可能会找到对“ zlib / gzip”(自Java 7开始的pdf处理或http编码),“ java2d”或“ jai”的引用。
但是要真正诊断本机内存泄漏,需要使用JIT代码符号映射和Linux最新的分析工具:perf
,perf-map-agent
和bcc
。
请参阅相关答案https://stackoverflow.com/a/52767721/737790
中的详细信息非常感谢Brendan Gregg