我使用命令java -Xmx240g mypackage.myClass
运行Java程序。
操作系统是Ubuntu 12.10。
top
命令显示MiB Mem 245743 total
,并且从一开始就显示Java进程virt 254g
,其中res
不断增加直到达到169g
。此时程序只有单线程,CPU%
大多数时间都为100%
,在某个点会跳到1300-2000(这是多线程垃圾回收器),然后res
缓慢移动到172g
。此时Java出现以下错误并崩溃:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
出错的位置是new double[2000][5]
这一行。
java -version
命令输出结果:
java version "1.7.0_15"
OpenJDK Runtime Environment (IcedTea7 2.3.7) (7u15-2.3.7-0ubuntu1~12.10)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
硬件是Amazon cr1.8xlarge实例。
看起来即使有大量内存可用,Java程序仍然会崩溃。这显然是不可能的,我必须误解了某些数字。我应该去哪里查找并理解出现问题的原因?
编辑:
我没有指定任何GC选项。唯一的命令行选项是-Xmx240g
。
我的程序在许多输入上都能正常工作,并且top
命令有时显示它使用了高达98.3%的内存。但是我使用特定的程序输入重现了上述情况。
编辑2:
这是一款科学应用程序。它有一个巨大的树(1-10百万个节点),每个节点都有一对大小约为300x3-900x5的double
数组。在初始树创建后,程序并不分配太多内存。大部分时间都会对这些数组进行一些算术运算。
编辑3:
HotSpot JVM也以相同的方式崩溃了,在170-172g时使用了大量CPU,并以相同的错误崩溃。看起来70-75%的内存是JVM不想越过的某条神奇线。
最终解决方案:使用-XX:+UseConcMarkSweepGC -XX:NewRatio=12,程序通过了170g标记并愉快地继续工作。