"-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

 About This Book

 Heap Memory Area and Size Control

 JVM Garbage Collection Logging

 Introduction of Garbage Collectors

Serial Collector - "+XX:+UseSerialGC"

 What Is Serial Collector

 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

 Garbage Collection Performance Test Summary

 References

 Full Version in PDF/EPUB