3

I set -Xmn1m -XX:SurvivorRatio=2, expect to see eden space to be 512K, but actually it is 0K.

It is really strange and I don't know why. I need your help.

vm options :-Xmx20m -Xms20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails

java version: 1.7.0_79

code and result is as followed:

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
Hearen
  • 7,420
  • 4
  • 53
  • 63
user3475810
  • 61
  • 1
  • 6

2 Answers2

2

I did some experiments with Java 7 and Java 8 and different options. The key point seems to be

  • Spaces have always sizes that are multiples of 512k and can’t be empty, so the smallest setup is “eden 1×512k, from 1×512k, to 1×512k”, which implies that you can’t have a new size smaller than 1536k. Also, the ratio constraint can only respected as far as possible with whole-number factors of the 512k unit size.

  • The numbers you specify are subject to rounding to multiples of 512k and enforcing the minimum size of 512k for each space, which is the first place showing inconsistencies. E.g. using Xmn1m with Java 8, I got a warning that the NewSize of 1536k (apparently already adapted) exceeds the MaxNewSize of 1024k (apparently not adapted yet), which is confusing as Xmn1m is supposed to set both to the same value, so saying that both are too small would be more understandable. Also, the warning only showed when using Xmn1m, resp. Xmn1024k, which are not subject to rounding, but was not shown for Xmn1023k or Xmn1025k.

  • Since the JVM doesn’t crash with that option, the adaptation seems to always result in reasonable values, but the code printing the statistics seems to have bugs (in Java 7 only), mixing the attempted configuration numbers with the numbers actually used by the JVM.

  • The total size reported for the Young Generation always includes the eden and from space only, ignoring the always-empty to space, which is inconsistent to the addresses reported behind the sizes, which include the complete span, covering all three spaces.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Holger
  • 285,553
  • 42
  • 434
  • 765
  • somehow related I think: https://www.google.com/url?sa=t&source=web&rct=j&url=https://stackoverflow.com/questions/43798527/hotsot-jvm-options&ved=0ahUKEwiz4IyYqbLXAhUCCewKHYOnAokQjjgIIjAA&usg=AOvVaw0D3I5GbJFe9_6olMMqlaRK – Eugene Nov 09 '17 at 20:25
2

This is a JVM bug introduced between JDK 7u40-b27 and JDK 7u40-b28.
Bug report JDK-8016309 is not publicly open.

Before JDK 7u40 the minimum size of heap region was 512 words (4KB). With the given JVM arguments the Eden size was correctly set to 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 increased the minimum region size to 65536 words (512KB).
Here is the related change. The same change has broken the sizing policy.
This resulted in assertion failure in debug builds of 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
#

There was no assertion failure in product builds, but rather the weird behavior you've observed.

The problem was noticed and fixed in JDK 8. The minimum possible size of young generation became 1536KB. I guess the fix was not suitable for backporting, so the bug remained in later updates of JDK 7.

However, it was decided to document the problem in JDK 7u40 release notes:

Area: hotspot/gc
Synopsis: New minimum young generation size is not properly checked by the JVM.

In JDK 7u40, the minimum size of the young generation for the parallel garbage collector was increased from 192 KB to 768 KB in a 32-bit JVM, and to 1536 KB in a 64-bit JVM. This new minimum size is not properly checked by the JVM. If a young generation size that is smaller than the new minimum is specified on the command line, it can result in either a crash or degraded performance.

The young generation size is set by the options -XX:NewSize= and -XX:MaxNewSize=, or by the option -Xmn (the latter option is equivalent to setting both NewSize and MaxNewSize to ). If the above options are not used, then the young generation size is computed as a fraction of the maximum heap size.

Workaround: Use a young generation size that is at least 768 KB (for 32-bit JVM) or 1536 KB (for 64-bit JVM).

apangin
  • 92,924
  • 10
  • 193
  • 247