Follow the code listing 3-5 from Understanding the Java Virtual Machine to do a local run.

The code is as follows:

public class GCTest {
    private static final int _1MB = 1024 * 1024;

    /**
     * -Xms20m
     * -Xmx20m
     * -Xmn10m
     * -XX:SurvivorRatio=8
     * -XX:+UseConcMarkSweepGC
     * -XX:+PrintGCDetails
     */
    public static void main(String[] args) {
        byte[] bytes1, bytes2, bytes3, bytes4;
        bytes1 = new byte[2 * _1MB];
        bytes2 = new byte[2 * _1MB];
        bytes3 = new byte[2 * _1MB];
        bytes4 = new byte[4 * _1MB];
    }
}
Copy the code

The print result is as follows:

[ParNew: 7035K->763K(9216K), 0.0149886 secs] 7035K->4862K(19456K), 0.0150353 secs] [Times: User =0.01 sys=0.00, real=0.02 secs] Heap PAR new Generation Total 9216K, used 7146K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000) eden space 8192K, 77% used [0x00000007bec00000, 0x00000007bf23b848, 0x00000007bf400000) from space 1024K, 74% used [0x00000007bf500000, 0x00000007bf5befc0, 0x00000007bf600000) to space 1024K, 0% used [0x00000007bf400000, 0x00000007bf400000, 0x00000007bf500000) concurrent mark-sweep generation total 10240K, used 4098K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000) Metaspace used 3062K, capacity 4496K, committed 4864K, reserved 1056768K class space used 327K, capacity 388K, committed 512K, reserved 1048576KCopy the code

Found not conforming to ideal conditions:

  • Ideally, gc should be triggered when the fourth object is allocated, and the first three objects cannot be destroyed until the method exits, reducing the total usage from 7035K to 4862K, which is not reasonable.
  • In the following snapshots, there should be only a fourth object in the Eden area, which occupies an inappropriate size.
  • The from area in the snapshot is not properly occupied, because the large object directly enters the old age.

For some reason, the fourth object is not gc when the fourth object is allocated, and the fourth object is commented out.

[ParNew: 7035K->770K(9216K), 0.0170803 secs] 7035K->4869K(19456K), 0.0171278 secs] [Times: User =0.03 sys=0.00, real=0.02 secs] Heap PAR new Generation Total 9216K, used 2901K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000) eden space 8192K, 26% used [0x00000007bec00000, 0x00000007bee14930, 0x00000007bf400000) from space 1024K, 75% used [0x00000007bf500000, 0x00000007bf5c0bb0, 0x00000007bf600000) to space 1024K, 0% used [0x00000007bf400000, 0x00000007bf400000, 0x00000007bf500000) concurrent mark-sweep generation total 10240K, used 4098K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000) Metaspace used 3068K, capacity 4496K, committed 4864K, reserved 1056768K class space used 327K, capacity 388K, committed 512K, reserved 1048576KCopy the code

It turns out that the gc dropped about 2M on the third object allocation, and it was not generated by the program code.

Given that the code was started with Intellij Idea, it could have been caused by it. Instead use the Java command to start:

➜ classes java-xMS20m-XMx20m-xmn10M-xx :SurvivorRatio= 8-xx :+ useconcmarkSweepgc-xx :+PrintGCDetails com/keygen/demo/test/GCTest [GC (Allocation Failure) [ParNew: [Times: 0.00228K, 0.00228k, 0.00228k] [Times: 0.00228k, 0.00228k] User =0.01 sys=0.00, real=0.01 secs] Heap PAR new Generation Total 9216K, used 4562K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000) eden space 8192K, 52% used [0x00000007bec00000, 0x00000007bf0290e0, 0x00000007bf400000) from space 1024K, 29% used [0x00000007bf500000, 0x00000007bf54b950, 0x00000007bf600000) to space 1024K, 0% used [0x00000007bf400000, 0x00000007bf400000, 0x00000007bf500000) concurrent mark-sweep generation total 10240K, used 6146K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000) Metaspace used 2618K, capacity 4486K, committed 4864K, reserved 1056768K class space used 277K, capacity 386K, committed 512K, reserved 1048576KCopy the code

The situation is consistent with the result in the book. The total memory usage basically does not decrease, and the Eden area usage in the snapshot is exactly the size of the fourth object. Others are objects that the program needs to execute and can be ignored.

Conclusion:

  • Intellij Idea executed the code and inserted its own logic, causing the GC logs to fall short of expectations.
  • The snapshot in the GC log is not a snapshot after the first object allocation after GC, such as the log printed for the first time. The Eden section contains more than one object.