具有16GB虚拟内存且不断增长的Java程序:这是一个问题吗?

Dav*_*vid 5 java performance virtual-memory

在Mac OSX 5.8上,我有一个Java程序,它运行在100%CPU很长一段时间 - 几天或更长时间(这是一个模型检查器分析并发程序,因此或多或少的预期).然而,它的虚拟内存大小,如OSX的活动监视器所示,在一天左右后变得非常庞大:现在它已经是16GB并且在不断增长.物理内存使用率大致稳定在1.1GB左右.

我想知道:16GB(并且还在增长)是一个问题的迹象,可能会减慢我的程序?

I start the program with "java -Xmx1024m -ea"

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-9M3326)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode)
Run Code Online (Sandbox Code Playgroud)

感谢大家的建议.我将尝试在一些答案中给出的分析建议并返回(可能需要一段时间,因为多天的运行时间).

在回答下面的一些要点时,模型检查器几乎不执行任何I/O(仅打印语句,具体取决于调试设置).在我使用的模式中它没有GUI.我不是模型检查器的主要作者(虽然我已经在它的一些内部工作),但我不相信它使用JNI.[<---编辑:这是错的,详情如下]它没有做任何内存映射.另外,我不是要求Oracle/Sun的JVM创建大量线程(请参阅下面的解释).

额外的虚拟内存没有导致模型检查器死亡,但是基于打印输出的频率,随着虚拟内存使用量的增加,它逐渐运行得越来越慢.(也许这只是因为垃圾收集越来越多.)我计划在周一在Windows机器上试用它,看看是否会发生同样的问题.

一点额外的解释:我正在运行的模型检查器(JPF)本身就是一个几乎完整的JVM(完全用Java编写),它运行在Oracle/Sun的JVM下.当然,作为虚拟机,JPF非常专业化以支持模型检查.

这有点违反直觉,但这意味着即使我模型检查的程序设计为多线程,就Sun的JVM而言,只有一个线程:运行JPF的线程.JPF模拟我的程序需要的线程作为其模型检查过程的一部分.


我相信斯蒂芬C已经指出了这个问题; Roland Illig给了我验证它的工具.我对JNI的使用是错误的.JPF本身不使用JNI,但它允许插件和JNI被其中一个配置的插件使用.幸运的是,我可以使用纯Java的等效插件.其中一个的初步使用显示在过去几个小时内虚拟内存没有增长.感谢大家的帮助.

Ste*_*n C 11

我怀疑它也是泄漏.但它不能泄漏"正常"内存,因为-Xmx1024m选项限制了正常堆.同样,它不会是'permgen'堆的泄漏,因为permgen的默认最大大小很小.

所以我怀疑它是以下之一:

  • 你正在泄漏线索; 即正在创建线程但未终止.它们可能不是活动的,但每个线程都有一个堆栈段(默认情况下为256k到1Mb,具体取决于平台),而不是在常规堆中分配.

  • 您正在泄漏直接映射文件.它们映射到由常规堆外部的OS分配的内存段.(@bestsss建议您查找泄露的ZIP文件句柄,我认为这是一个子案例.)

  • 您正在使用一些泄漏malloc内存或类似内容的JNI/JNA代码.

无论哪种方式,内存分析器都可能隔离问题,或者至少消除一些可能性.


JVM内存泄漏也是可能的,但是在您明确消除您自己的代码和正在使用的库/应用程序中的可能原因之前,开始怀疑JVM是不明智的.