我设置-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
答案 0 :(得分:2)
我使用Java 7和Java 8以及不同的选项进行了一些实验。关键点似乎是
空格的大小始终是512k
的倍数,不能为空,因此最小的设置是“eden 1×512k
,从1×512k
到{{1 “},这意味着您的新尺寸不能小于1×512k
。此外,只有1536k
单位大小的整数因子才能尽可能地考虑比率约束。
您指定的数字可以舍入为512k
的倍数,并为每个空格强制执行512k
的最小尺寸,这是第一个显示不一致的地方。例如。在Java 8中使用512k
时,我收到一条警告:Xmn1m
NewSize
(显然已经适应)超过了1536k
的{{1}}(显然还没有改编) ),这是令人困惑的,因为MaxNewSize
应该将两者都设置为相同的值,所以说两者都太小将更容易理解。此外,警告仅在使用1024k
时显示。 Xmn1m
,不受四舍五入的影响,但未针对Xmn1m
或Xmn1024k
显示。
由于JVM没有使用该选项崩溃,因此适配似乎总是会产生合理的值,但打印统计信息的代码似乎有错误(仅限Java 7),将尝试的配置号与JVM实际使用的数字。
为Young Generation报告的总大小始终仅包含 eden 和来自空间,忽略始终为空 空间,与尺寸背后报告的地址不一致,包括完整的跨度,覆盖所有三个空间。
答案 1 :(得分:2)
这是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中记录问题:
区域:hotspot / 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)。