看<<实战java虚拟机>>书,运行一个demo,然后报了以下的错误提示。
Java HotSpot™ 64-Bit Server VM warning: NewSize (1536k) is greater than the MaxNewSize (1024k). A new max generation size of 1536k will be used.
测试代码为:
package cn.shutdown.demo.jvm;
/**
* -Xmx20m -Xms20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails
* @author dmn
* @date 2021/6/15
*/
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];
}
}
}
运行结果为:
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.
[GC (Allocation Failure) [PSYoungGen: 512K->496K(1024K)] 512K->512K(19968K), 0.0015693 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 1024K, used 738K [0x00000007bfe80000, 0x00000007c0000000, 0x00000007c0000000)
eden space 512K, 47% used [0x00000007bfe80000,0x00000007bfebc8d0,0x00000007bff00000)
from space 512K, 96% used [0x00000007bff00000,0x00000007bff7c010,0x00000007bff80000)
to space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000)
ParOldGen total 18944K, used 10256K [0x00000007bec00000, 0x00000007bfe80000, 0x00000007bfe80000)
object space 18944K, 54% used [0x00000007bec00000,0x00000007bf6040a0,0x00000007bfe80000)
Metaspace used 2700K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 289K, capacity 386K, committed 512K, reserved 1048576K
对这个警告提示很好奇,于是搜了搜,在StackOverflow里找到一个非常靠谱的答案。
JDK7 JVM different from JDK8
说明如下
The observed behaviour is related to some changes between Java 7 and Java 8.
这个情况与jdk7和jdk8中的变更有关
-Xmn1024k
this option sets the
initial
and themaximum
size of the heap for the young generation. It’s a shorthand for-XX:NewSize=1024k -XX:MaxNewSize=1024k
.
这个jvm参数项设置 青年代堆内存的初始和最大的空间。是 -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
...
This behaviour seems to be not in line with the documentation.
这种行为似乎与文档不符。
-Xmnsize or -XX:NewSize Sets the size of the young generation (nursery).
The -XX:NewSize option is equivalent to -Xmn.
Because
-XX:NewSize=2048k
would set in Java7/8 only the initial size and the maximum size is chosen by the JVM.
因为 -XX:NewSize=2048k
会在 Java7/8 中设置只有初始大小,最大大小由 JVM 选择。
Hence if you specify
-Xmn1024k
it actually means you want to set
因此,如果你指定-Xmn1024k
意味着你想要设置如下
-XX:NewSize=1024k -XX:MaxNewSize=1024k
In Java 7 (tested with 1.7.0_40-b43) the minimal size (for initial and maximum) is
196608
. If you set the value to low. The start of the JVM fails with
在Java7中,(初始化和最大值)的范围的最小值为 196608,如果设置的值比这个值小,JVM虚拟机启动就会报下面的错误而失败。
Error occurred during initialization of VM
Too small new size specified
In Java 8 (tested with 1.8.0_74-b02) minimal size (for initial and maximum) is
1572864
(1536K).
在Java8中,(初始化和最大值)的范围的最小值为1572864
(1536K).
Now why you get this
NewSize (1536k) is greater than the MaxNewSize (1024k)
with Java 8.
所以java8中的,1536k是大于你设置的 -Xmn1m (-Xmn1024k) 的。
If you choose
NewSize
lower than the minimal size (1536K) it’s adjusted silently to that minimal size.
如果你选择的NewSize
初始化的值小于取值范围的最低值,那会自动被设置为最低值(1536k)
java -XX:+PrintFlagsFinal -XX:NewSize=1k -version | grep NewSize
...
uintx NewSize := 1572864
...
If you choose
MaxNewSize
lower thanNewSize
,MaxNewSize
will be set silently toNewSize
如果 MaxNewSize
的值小于 NewSize
, MaxNewSize
的值会被自动设置为NewSize
的值。
java -XX:+PrintFlagsFinal -XX:NewSize=2048k -XX:MaxNewSize=1025k -version | \
grep NewSize
...
uintx MaxNewSize := 2097152
uintx NewSize := 2097152
...
If you choose
NewSize
andMaxNewSize
lower than minimal size andMaxNewSize
bigger thanNewSize
, both are set to the minimal size.
NewSize
和MaxNewSize
的值如果都低于最小值(1536k),则都会被设置为最小值(1536k)。
java -XX:+PrintFlagsFinal -XX:NewSize=1024k -XX:MaxNewSize=1025k -version | \
grep NewSize
...
uintx MaxNewSize := 1572864
uintx NewSize := 1572864
...
java -XX:+PrintFlagsFinal -XX:NewSize=1 -XX:MaxNewSize=1025k -version | \
grep NewSize
...
uintx MaxNewSize := 1572864
uintx NewSize := 1572864
...
But as soon you choose for
MaxNewSize
a value lower than1025k
equal to1024k
you get the error message you have discovered. Seems you found an edge case where a check is done before the adjustment.
但是,一旦您为“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.
That’s explains why
java -Xmn1025k -version
runs fine where asjava -Xmn1024k -version
gives you the error message.
这就是为什么执行 java -Xmn1025k -version
正常跑,但是 java -Xmn1024k -version
报错了。
After some more testing. The error seems to be printed only in case
MaxNewSize
is equal to1024k
. The next examples are working with the default size forNewSize
andMaxNewSize
.
经过测试,这个错误只会在 MaxNewSize
的值为 1024k
的时候进行输出。
java -XX:NewSize=1 -XX:MaxNewSize=1023k -version
java -XX:NewSize=1 -XX:MaxNewSize=1 -version