我设置-Xmn1m -XX:SurvivorRatio=2
,期望看到伊甸园空间是512K
,但实际上它是0K
。
这真的很奇怪,我不知道为什么。我需要你的帮助。
vm选项:-Xmx20m -Xms20m -Xmn1m -XX:SurvivorRatio = 2 -XX:+ PrintGCDetails
java版本:1.7.0_79
代码和结果如下:
public class NewSizeDemo {
public static void main(String[] args){
byte[] b = null;
for (int i=0; i<10; i++){
b = new byte[1*1024*1024];
}
}
}
Heap
PSYoungGen total 512K, used 0K [0x00000007fff00000, 0x0000000800000000, 0x0000000800000000)
eden space 0K, -2147483648% used [0x00000007fff00000,0x00000007fff00000,0x00000007fff00000)
from space 512K, 0% used [0x00000007fff80000,0x00000007fff80000,0x0000000800000000)
to space 512K, 0% used [0x00000007fff00000,0x00000007fff00000,0x00000007fff80000)
ParOldGen total 19456K, used 11573K [0x00000007fec00000, 0x00000007fff00000, 0x00000007fff00000)
object space 19456K, 59% used [0x00000007fec00000,0x00000007ff74d5a0,0x00000007fff00000)
PSPermGen total 21504K, used 2996K [0x00000007f9a00000, 0x00000007faf00000, 0x00000007fec00000)
object space 21504K, 13% used [0x00000007f9a00000,0x00000007
这是JDK 7u40-b27和JDK 7u40-b28之间引入的JVM错误。 错误报告JDK-8016309未公开。
在JDK 7u40之前,堆区域的最小大小为512字(4KB)。使用给定的JVM参数,Eden大小已正确设置为512K:
PSYoungGen total 768K, used 287K [0x00000000fff00000, 0x0000000100000000, 0x0000000100000000)
eden space 512K, 56% used [0x00000000fff00000,0x00000000fff47e08,0x00000000fff80000)
from space 256K, 0% used [0x00000000fffc0000,0x00000000fffc0000,0x0000000100000000)
to space 256K, 0% used [0x00000000fff80000,0x00000000fff80000,0x00000000fffc0000)
JDK-6725714将最小区域大小增加到65536字(512KB)。 这是related change。同样的变化打破了规模调整政策。 这导致JVM的调试版本中的断言失败:
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (/home/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp:183), pid=10261, tid=1081264448
# assert(eden_size > 0 && survivor_size > 0) failed: just checking
#
产品构建中没有断言失败,而是您观察到的奇怪行为。
在JDK 8中注意到并修复了该问题。年轻一代的最小可能大小变为1536KB。我想这个修复程序不适合后向移植,因此该错误仍然存在于JDK 7的后续更新中。
但是,决定记录JDK 7u40 release notes中的问题:
区域:热点/ gc 概要:JVM未正确检查新的最小年代大小。
在JDK 7u40中,并行垃圾收集器的年轻代的最小大小在32位JVM中从192 KB增加到768 KB,在64位JVM中增加到1536 KB。 JVM未正确检查此新的最小大小。如果在命令行中指定了小于新最小值的年轻代,则可能导致崩溃或性能下降。
年轻代的大小由选项-XX:NewSize =和-XX:MaxNewSize =设置,或者由选项-Xmn设置(后一个选项相当于将NewSize和MaxNewSize设置为)。如果未使用上述选项,则将年轻代大小计算为最大堆大小的一部分。
解决方法:使用至少768 KB(对于32位JVM)或1536 KB(对于64位JVM)的年轻代。
我做了一些Java 7和Java 8以及不同选项的实验。关键点似乎是
512k
的倍数,不能为空,所以最小的设置是“eden 1×512k
,从1×512k
到1×512k
”,这意味着你不能有一个小于1536k
的新尺寸。此外,比率约束只能尽可能地与512k
单位大小的整数因子一致。512k
的倍数,并强制执行每个空格的512k
的最小大小,这是第一个显示不一致的地方。例如。使用Xmn1m
和Java 8,我得到一个警告,NewSize
(显然已经适应)的1536k
超过MaxNewSize
的1024k
(显然还没有适应),这是令人困惑的,因为Xmn1m
应该设置两个相同的值,所以说两者都太小会更容易理解。此外,警告只显示使用Xmn1m
,resp。 Xmn1024k
,不受四舍五入,但没有显示为Xmn1023k
或Xmn1025k
。