JDK7 JVM与JDK8不同

时间:2017-08-18 03:11:18

标签: java jvm

当我运行此代码时

public static void main(String[] args) {
    byte[] b = null;
    for(int i=0;i<10;i++)
        b = new byte[1024 * 1024];
}

在JDK7中使用JVM选项-Xmx20m -Xms20m -Xmn1m -XX:+PrintGCDetails,将打印控制台 enter image description here。当我在JDK8中使用此JVM选项运行时,它将打印

Error occurred during initialization of VM
GC triggered before VM initialization completed. Try increasing NewSize, current value 1536K.
Java HotSpot(TM) 64-Bit Server VM warning: NewSize (1536k) is greater than the MaxNewSize (1024k). A new max generation size of 1536k will be used.

为什么?

2 个答案:

答案 0 :(得分:0)

错误消息包含原因。

  

在VM初始化完成之前触发了GC。

它与您的代码无关,因为VM初始化发生在main运行之前。

答案 1 :(得分:0)

观察到的行为与Java 7和Java 8之间的一些变化有关。

-Xmn1024k

此选项为年轻代设置堆的initialmaximum大小。它是-XX:NewSize=1024k -XX:MaxNewSize=1024k的缩写。

// same command in Java 7/8
java -XX:+PrintFlagsFinal -Xmn2048k -version | grep NewSize
...
uintx MaxNewSize                               := 2097152
uintx NewSize                                  := 2097152
...

此行为似乎与文档不符。

Java 7

  

-Xmnsize或-XX:NewSize   设定年轻一代(托儿所)的大小。

Java 8

  

-XX:NewSize选项相当于-Xmn。

因为-XX:NewSize=2048k将在Java7 / 8中设置,所以JVM只选择初始大小和最大大小。

因此,如果您指定-Xmn1024k,则实际上意味着您要设置

-XX:NewSize=1024k -XX:MaxNewSize=1024k

在Java 7中(使用1.7.0_40-b43测试),最小大小(初始和最大)为196608。如果将值设置为低。 JVM的启动失败,带有

Error occurred during initialization of VM
Too small new size specified

在Java 8中(使用1.8.0_74-b02测试)最小大小(初始和最大)为1572864(1536K)。

现在为什么你用Java 8获得这个NewSize (1536k) is greater than the MaxNewSize (1024k)

如果您选择NewSize低于最小尺寸(1536K),则会默默调整到最小尺寸。

java -XX:+PrintFlagsFinal -XX:NewSize=1k -version | grep NewSize
...
uintx NewSize                                  := 1572864
...

如果您选择MaxNewSize低于NewSize MaxNewSize,则会默默设置为NewSize

java -XX:+PrintFlagsFinal -XX:NewSize=2048k -XX:MaxNewSize=1025k -version | \
    grep NewSize
...
uintx MaxNewSize                               := 2097152
uintx NewSize                                  := 2097152
...

如果您选择NewSizeMaxNewSize低于最小尺寸且MaxNewSize大于NewSize,则两者都设置为最小尺寸。

java -XX:+PrintFlagsFinal -XX:NewSize=1024k -XX:MaxNewSize=1025k -version | \
    grep NewSize
...
uintx MaxNewSize                               := 1572864
uintx NewSize                                  := 1572864
...

这甚至适用于NewSize

的完全低值
java -XX:+PrintFlagsFinal -XX:NewSize=1 -XX:MaxNewSize=1025k -version | \
    grep NewSize
...
uintx MaxNewSize                               := 1572864
uintx NewSize                                  := 1572864
...

但是,一旦您为MaxNewSize选择的值低于1025k 等于1024k,您就会收到您发现的错误消息。似乎你找到了一个在调整之前进行检查的边缘情况。

java -XX:NewSize=1 -XX:MaxNewSize=1025k -version
java version "1.8.0_74"

java -XX:NewSize=1 -XX:MaxNewSize=1024k -version
Java HotSpot(TM) 64-Bit Server VM warning: NewSize (1536k) is greater than the \
MaxNewSize (1024k). A new max generation size of 1536k will be used.

这解释了为什么java -Xmn1025k -versionjava -Xmn1024k -version为您提供错误消息时正常运行。

编辑经过多次测试。仅在MaxNewSize等于1024k的情况下才会打印错误。接下来的示例使用NewSizeMaxNewSize的默认大小。

java -XX:NewSize=1 -XX:MaxNewSize=1023k -version
java -XX:NewSize=1 -XX:MaxNewSize=1 -version