In this article, we will discuss the following topics:
- Humongous regions and humongous allocations
- How humongous allocations impact G1's performance?
- How to detect humongous allocations?
- Basic Investigation
- Advanced Investigation
Humongous Regions and Humongous Allocations
A humongous object is allocated directly in the humongous regions. These humongous regions are a contiguous set of regions. StartsHumongous marks the start of the contiguous set and ContinuesHumongous marks the continuation of the set.
Before allocating any humongous region, the marking threshold is checked, initiating a concurrent cycle, if necessary. Dead humongous objects are freed at the end of the marking cycle during the cleanup phase also during a full garbage collection cycle (but, a new implementation has changed this; see the next section).
Since each individual set of StartsHumongous and ContinuesHumongous regions contains just one humongous object, the space between the end of the humongous object and the end of the last region spanned by the object is unused. For objects that are just slightly larger than a multiple of the heap region size, this unused space can cause the heap to become fragmented.
How Humongous Allocations Impact G1's Performance?
In the old implementation, humongous objects are not released until after a full concurrent marking cycle. This is far from ideal for many transaction-based enterprise applications that create short-lived (i.e., in the transaction scope) humongous objects such as ResultSet(s) generated from JDBC queries. This results in the heap filling up relatively quickly and leads to unnecessary marking cycles to reclaim them.
A new implementation since:
java version "1.8.0_40-ea"handles humongous regions differently and can reclaim them earlier if they are short-lived (see  for details).
Java(TM) SE Runtime Environment (build 1.8.0_40-ea-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b05, mixed mode)
For investigating humongous allocations in G1, you should begin with the following minimal set of VM options:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintReferenceGC (-XX:+UseG1GC)
Basic Humongous Allocation Investigation
For basic humongous allocations investigation, you simply add a new option:
This option will print out something like below:
12025.832: [G1Ergonomics (Concurrent Cycles) request concurrent cycle initiation, reason: occupancy higher than threshold, occupancy: 3660578816 bytes, allocation request: 1048592 bytes, threshold: 3650722120 bytes (85.00 %), source: concurrent humongous allocation]
From the above, we saw a humongous allocation is initiated with a request size of 1048592 bytes. Note that our region size is 1MBytes in this test. So, the request object is considered as humongous (i.e., 1048592 Bytes > half of 1 MBytes).
In the output, you can also find the following entries:
[Humongous Reclaim: 0.0 ms] [Humongous Total: 54] [Humongous Candidate: 0] [Humongous Reclaimed: 0]
Advanced Humongous Allocation Investigation
To further investigate humongous allocation in more details, you can add:
Note that the following VM options are experimental:
-XX:+PrintAdaptiveSizePolicy -XX:+UnlockExperimentalVMOptions -XX:+G1ReclaimDeadHumongousObjectsAtYoungGC -XX:G1LogLevel=finest -XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC
G1LogLevel (i.e., [fine|finer|finest])
So, that's why we added the unlock option;
With extra printing options, you will find detailed description of humongous allocations as shown below:
3708.669: [SoftReference, 0 refs, 0.0000340 secs]3708.669: [WeakReference, 1023 refs, 0.0001790 secs]3708.669: [FinalReference, 295 refs, 0.0007020 secs]3708.670: [PhantomReference, 0 refs, 0.0000060 secs]3708.670: [JNI Weak Reference, 0.0000140 secs]Live humongous 1 region 9 size 65538 with remset 1 code roots 0 is marked 0 live-other 0 obj array 0 Live humongous 1 region 10 size 88066 with remset 1 code roots 0 is marked 0 live-other 0 obj array 0 Live humongous 1 region 15 size 262146 with remset 1 code roots 0 is marked 0 live-other 0 obj array 1 ...
Finally, you can also use Java Flight Recorder (JFR) and Java Mission Control (JMC) to get information about humongous objects by showing their allocation sources with stack traces.
Early reclaim of large objects that are referenced by a few objects
Java Mission Control (JMC) and Java Flight Recorder (JFR)
- Garbage First Garbage Collector Tuning
- G1GC: Migration to, Expectations and Advanced Tuning
- Thread local allocation buffers (TLAB's)
- Early reclamation of large objects in G1
- Introduced since 8u40 b02 and 8u45
- Was not back ported to 8u20
- Prints information about live and dead humongous objects
- (Before bug fix) prints that information when there is at least one humongous candidate.
- (After bug fix) prints that information even when there is no humongous candidates; it also prints humongous object size in the output