在MacOSX5.8上,我有一个在100% CPU上运行很长时间的Java程序--几天或更长时间(它是一个分析并发程序的模型检查器,所以这或多或少是预期的)。然而,它的虚拟内存大小,如OSX的Activity所示,在一天左右之后就变得巨大了:现在它只有16 in,而且还在增长。物理内存的使用大致稳定在1.1GB左右。
我想知道:16 my (而且还在增长)是否是一个问题的迹象,可能会减慢我的程序?
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)感谢大家的建议。我将尝试在一些答案中给出的分析建议,然后回来(这可能需要一段时间,因为多天运行时间)。
为了回答下面的一些问题,模型检查器几乎不执行I/O (仅打印语句,取决于调试设置)。在我使用的模式中,它没有GUI。我不是模型检查器的主要作者(虽然我研究过它的一些内部结构),但我不认为它使用了JNI。<--编辑:这是错误的,下面的细节它不做任何内存映射。此外,我并不要求Oracle/Sun的JVM创建大量线程(请参见下面的解释)。
额外的虚拟内存并没有导致模型检查器死掉,但是根据打印输出的频率,随着虚拟内存使用量的增加,它的运行速度也越来越慢。(也许这只是因为越来越多的垃圾收集。)我计划周一在Windows机器上试用,看看是否会出现同样的问题。
还有一点额外的解释:我正在运行的模型检查器(JPF)本身就是一个几乎完整的JVM (完全用Java编写),运行在Oracle/Sun的JVM下。当然,作为虚拟机,JPF是支持模型检查的高度专业化的。
这有点违背直觉,但这意味着即使我的程序模型检查是设计为多线程的,但就Sun的JVM而言,只有一个线程:运行JPF的线程。JPF模拟我的程序所需的线程,作为其模型检查过程的一部分。
我相信Stephen已经指出了这个问题;Roland给了我验证这个问题的工具。我对JNI的使用错了。JPF本身不使用JNI,但它允许插件和JNI被配置的插件之一使用。幸运的是,我可以使用类似的插件,这些插件都是纯Java的。其中之一的初步使用显示,在过去的几个小时里,虚拟内存没有增长。感谢大家的帮助。
发布于 2011-06-05 05:47:12
我怀疑这也是个漏洞。但是它不可能是“正常”内存的泄漏,因为-Xmx1024m选项正在限制正常堆。同样,它不会是' permgen‘堆的泄漏,因为permgen的默认最大大小是小的。
因此,我怀疑这是以下其中之一:
无论哪种方式,内存分析器都可能隔离问题,或者至少消除一些可能性。
JVM内存泄漏也是一种可能性,但在您自己使用的代码和库/应用程序中彻底消除了可能的原因之前,开始怀疑JVM是不明智的。
发布于 2011-06-05 05:57:34
由于您的应用程序不是实时应用程序,所以可以执行以下操作:
jps -v从该表中获取进程id,并将其保存为pid。
jmap -histo $pid > before-gc.hgr
jmap -histo:live $pid > after-gc.hgr
jstack -v $pid > threads.txtthreads.txt文件告诉您进程目前正在做什么。
堆使用直方图before-gc.hgr和after-gc.hgr告诉您一个完整的垃圾回收可以释放多少内存。
也许你会从中得到一些关于正在发生的事情的提示。
发布于 2011-06-05 05:02:23
完成对象后,您是否正确地对所有引用进行NULL处理?我想知道这是否是一个简单的内存泄漏。
我在C程序中看到了这种行为,这些程序为不同大小的对象混合了大量的分配和释放。您可以得到内存页的一半使用,但没有任何足够大的漏洞,可以用来满足新的内存请求。
这不仅会导致交换,而且会随着时间的推移破坏引用的局部性--交换会变得更糟。
C程序中的解决方案通常是切换到板坯分配器,并将不同大小的对象保存在不同的内存页上。不再有奇数大小的洞,而且总是有一个指向空间的指针,无论你的对象是什么,空间的大小都是合适的。
当然,在像Java这样的托管环境中这样做可能很困难。人们可能希望JVM已经在这样做了。(考虑到托管环境可以更新对新内存位置的引用并定期重新打包,即使是简单的内存分配方法也应该防止愚蠢的漏洞。)
有问题的迹象通常来自交换流量。如果您在您的系统上看到大量交换通信量,即使进程的RSS (驻留集大小)保持稳定,那么您可能要为看起来完全在内存中运行的操作执行大量的磁盘IO。在Linux和其他一些Unix系统上,您可以使用vmstat 1命令找到交换流量信息:
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 0 727392 351128 3846980 0 0 13 16 41 73 3 1 96 0
0 0 0 727392 351128 3846988 0 0 0 0 1267 4742 5 1 95 0
...si和so列每秒显示块。(嗯,无论您在vmstat 1或vmstat 2中选择了什么时间间隔,等等。)
如果交换流量很低,那么您可能没有什么可担心的。如果交换流量很高,那么一定要设法找出交换的原因。这需要更多的工作。:)
https://stackoverflow.com/questions/6240985
复制相似问题