Java GC Tutorials - Herong's Tutorial Examples - v1.11, by Dr. Herong Yang
"-XX:+NeverTenure" and "-XX:+AlwaysTenure" Working
This section provides a tutorial showing '-XX:+NeverTenure' and '-XX:+AlwaysTenure' JVM options are working with the Serial collector.
HotSpot JVM also support two hidden options you can use to control tenuring behavior:
First, let's try "-XX:+NeverTenure" with our test program GarbageCollection2.java:
herong> java -Xms130m -Xmx130m -XX:+UseSerialGC \ -XX:NewSize=120m -XX:SurvivorRatio=1 \ -XX:TargetSurvivorRatio=99 -XX:+NeverTenure \ -Xlog:gc=info,gc+heap=debug,gc+age=trace GarbageCollection2 ... 560 94371840 17086360 77285480 [gc,heap] GC(14) Heap before GC invocations=14 (full 0): def new ... [gc,heap] GC(14) eden space 40960K, 99% used [... [gc,heap] GC(14) from space 40960K, 84% used [... [gc,heap] GC(14) to space 40960K, 0% used [... [gc,heap] GC(14) tenured generation total 10240K, used 0K [... [gc,heap] GC(14) the space 10240K, 0% used [... [gc,age ] GC(14) Desired survivor size 41523608 bytes, new threshold 16 (max threshold 16) [gc,age ] GC(14) Age table with threshold 16 (max threshold 16) [gc,age ] GC(14) - age 1: 23069216 bytes, 23069216 total [gc,age ] GC(14) - age 2: 8388736 bytes, 31457952 total [gc,age ] GC(14) - age 3: 1048592 bytes, 32506544 total [gc,age ] GC(14) - age 12: 56 bytes, 32506600 total [gc,age ] GC(14) - age 13: 80 bytes, 32506680 total [gc,age ] GC(14) - age 14: 736 bytes, 32507416 total [gc,age ] GC(14) - age 15: 2945800 bytes, 35453216 total [gc,heap] GC(14) DefNew: 75474K->34622K(81920K) [gc,heap] GC(14) Tenured: 0K->0K(10240K) [gc ] GC(14) Pause Young (Allocation Failure) 73M->33M(90M) 10.911ms [gc,heap] GC(14) Heap after GC invocations=15 (full 0): def new ... [gc,heap] GC(14) eden space 40960K, 0% used [... [gc,heap] GC(14) from space 40960K, 84% used [... [gc,heap] GC(14) to space 40960K, 0% used [... [gc,heap] GC(14) tenured generation total 10240K, used 0K [... [gc,heap] GC(14) the space 10240K, 0% used [... 561 94371840 57870032 36501808 ... 599 94371840 17202040 77169800 [gc,heap] GC(15) Heap before GC invocations=15 (full 0): def new ... [gc,heap] GC(15) eden space 40960K, 99% used [... [gc,heap] GC(15) from space 40960K, 84% used [... [gc,heap] GC(15) to space 40960K, 0% used [... [gc,heap] GC(15) tenured generation total 10240K, used 0K [... [gc,heap] GC(15) the space 10240K, 0% used [... [gc,age ] GC(15) Desired survivor size 41523608 bytes, new threshold 16 (max threshold 16) [gc,age ] GC(15) Age table with threshold 16 (max threshold 16) [gc,age ] GC(15) - age 1: 23069024 bytes, 23069024 total [gc,age ] GC(15) - age 2: 5243152 bytes, 28312176 total [gc,age ] GC(15) - age 3: 4194368 bytes, 32506544 total [gc,age ] GC(15) - age 13: 56 bytes, 32506600 total [gc,age ] GC(15) - age 14: 80 bytes, 32506680 total [gc,age ] GC(15) - age 15: 2946536 bytes, 35453216 total [gc,heap] GC(15) DefNew: 75361K->34622K(81920K) [gc,heap] GC(15) Tenured: 0K->0K(10240K) [gc ] GC(15) Pause Young (Allocation Failure) 73M->33M(90M) 10.560ms [gc,heap] GC(15) Heap after GC invocations=16 (full 0): def new ... [gc,heap] GC(15) eden space 40960K, 0% used [... [gc,heap] GC(15) from space 40960K, 84% used [... [gc,heap] GC(15) to space 40960K, 0% used [... [gc,heap] GC(15) tenured generation total 10240K, used 0K [... [gc,heap] GC(15) the space 10240K, 0% used [...
Log messages from GC #16, GC(15), confirm that "-XX:+NeverTenure" option is working. 2946536 bytes of objects "age 15", was the sum of 2945800 bytes of objects grew from "age 14" from last GC and 2945800 bytes of objects matured from "age 15 from last GC. "-XX:+NeverTenure" option forced all matured objects to stay in Young generation as "age 15" forever.
Now, let's try "-XX:+AlwaysTenure" with our test program GarbageCollection2.java:
herong> java -Xms240m -Xmx240m -XX:+UseSerialGC \ -XX:NewSize=120m -XX:SurvivorRatio=1 \ -XX:TargetSurvivorRatio=99 -XX:+AlwaysTenure \ -Xlog:gc=info,gc+heap=debug,gc+age=trace GarbageCollection2 ... 16 209715200 168575600 41139600 [gc,heap] GC(0) Heap before GC invocations=0 (full 0): def new ... [gc,heap] GC(0) eden space 40960K, 98% used [... [gc,heap] GC(0) from space 40960K, 0% used [... [gc,heap] GC(0) to space 40960K, 0% used [... [gc,heap] GC(0) tenured generation total 122880K, used 0K [... [gc,heap] GC(0) the space 122880K, 0% used [... [gc,age ] GC(0) Desired survivor size 41523608 bytes, new threshold 0 (max threshold 0) [gc,age ] GC(0) Age table with threshold 0 (max threshold 0) [gc,heap] GC(0) DefNew: 40175K->0K(81920K) [gc,heap] GC(0) Tenured: 0K->16225K(122880K) [gc ] GC(0) Pause Young (Allocation Failure) 39M->15M(200M) 11.782ms [gc,heap] GC(0) Heap after GC invocations=1 (full 0): def new ... [gc,heap] GC(0) eden space 40960K, 0% used [... [gc,heap] GC(0) from space 40960K, 0% used [... [gc,heap] GC(0) to space 40960K, 0% used [... [gc,heap] GC(0) tenured generation total 122880K, used 16225K [... [gc,heap] GC(0) the space 122880K, 13% used [... 17 209715200 192051408 17663792 ... 209 209715200 55961104 153754096 [gc,heap] GC(5) Heap before GC invocations=5 (full 0): def new ... [gc,heap] GC(5) eden space 40960K, 99% used [... [gc,heap] GC(5) from space 40960K, 0% used [... [gc,heap] GC(5) to space 40960K, 0% used [... [gc,heap] GC(5) tenured generation total 122880K, used 109412K [... [gc,heap] GC(5) the space 122880K, 89% used [... [gc ] GC(6) Pause Full (Allocation Failure) 146M->33M(200M) 12.399ms [gc,heap] GC(5) DefNew: 40738K->0K(81920K) [gc,heap] GC(5) Tenured: 109412K->34634K(122880K) [gc ] GC(5) Pause Young (Allocation Failure) 146M->33M(200M) 12.482ms [gc,heap] GC(5) Heap after GC invocations=6 (full 1): def new ... [gc,heap] GC(5) eden space 40960K, 0% used [... [gc,heap] GC(5) from space 40960K, 0% used [... [gc,heap] GC(5) to space 40960K, 0% used [... [gc,heap] GC(5) tenured generation total 122880K, used 34634K [... [gc,heap] GC(5) the space 122880K, 28% used [...
As you can see from those log messages, "-XX:+AlwaysTenure" option is working. Live objects were promoted directly from "eden" to "tenured" generation immediately at GC(0). "from" and "to" spaces were not used at all. When "tenured" generation was full, a Full GC was performed, see GC(5) and GC(6).
Conclusion:
Table of Contents
Heap Memory Area and Size Control
JVM Garbage Collection Logging
Introduction of Garbage Collectors
►Serial Collector - "+XX:+UseSerialGC"
GC Log Message Format for Serial Collector
GC Log Message Examples of Serial Collector
Log Message Types from Serial Collector
Serial Collector Stops Application for Minor/Major GC
Usage Report on Heap Memory Areas
Default NewRatio - Old vs. New Generation
"-XX:NewRatio" - Ratio of Tenured and "new" Generation
"-XX:SurvivorRatio" - Ratio of Eden and Survivor Space
Serial GC Tracing - Tight Heap
Serial GC Tracing - Tight Heap (Part 2)
Serial GC Tracing - Tight Heap (Part 3)
Serial GC Tracing - Plenty of Heap
Serial GC Tracing - Aged Live Objects
Serial GC Tracing - Tenuring Threshold
"-XX:TargetSurvivorRatio" - Second Tenuring Condition
Serial GC Tracing - Tenuring Threshold Controlled
►"-XX:+NeverTenure" and "-XX:+AlwaysTenure" Working
Minor GC Triggering Condition of Serial Collector
Parallel Collector - "+XX:+UseParallelGC"
Concurrent Mark-Sweep (CMS) Collector - "+XX:+UseConcMarkSweepGC"
Garbage First (G1) Collector - "+XX:+UseG1GC"
The Z Garbage Collector (ZGC) - "+XX:+UseZGC"
Object References and Garbage Collection
Garbage Collection Performance Test Program
Performance Tests on Serial Collector
Performance Tests on Parallel collector
Performance Tests on Concurrent collector
Performance Tests on G1 collector