为什么-Xmn1m -XX:SurvivorRatio = 2使eden空间为0k

问题描述 投票:3回答:2

我设置-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
java jvm java-7
2个回答
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中的问题:

区域:热点/ 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)的年轻代。


2
投票

我做了一些Java 7和Java 8以及不同选项的实验。关键点似乎是

  • 空间总是大小是512k的倍数,不能为空,所以最小的设置是“eden 1×512k,从1×512k1×512k”,这意味着你不能有一个小于1536k的新尺寸。此外,比率约束只能尽可能地与512k单位大小的整数因子一致。
  • 您指定的数字可以舍入为512k的倍数,并强制执行每个空格的512k的最小大小,这是第一个显示不一致的地方。例如。使用Xmn1m和Java 8,我得到一个警告,NewSize(显然已经适应)的1536k超过MaxNewSize1024k(显然还没有适应),这是令人困惑的,因为Xmn1m应该设置两个相同的值,所以说两者都太小会更容易理解。此外,警告只显示使用Xmn1m,resp。 Xmn1024k,不受四舍五入,但没有显示为Xmn1023kXmn1025k
  • 由于JVM不会因该选项而崩溃,因此适应似乎总是会产生合理的值,但打印统计信息的代码似乎有错误(仅限Java 7),将尝试的配置号与实际使用的数字混合在一起。 JVM。
  • 报告的年轻一代的总大小总是包括伊甸园和仅来自太空,忽略始终为空的空间,这与大小背后报告的地址不一致,其中包括覆盖所有三个空间的完整跨度。
© www.soinside.com 2019 - 2024. All rights reserved.