I’m currently working on a Java application that makes use of humongous allocations and regions. Typically, I would monitor these allocations and regions using the GC (Garbage Collection) logs. However, in this case, I am looking for alternative methods to print out humongous allocations within the JVM, just like I can see the attributes of Eden/Survivor/Old Spaces in the memoryPoolMXBean.
GCLog:
G1 Eden Space memory used: 0 (0.0%)
G1 Old Gen memory used: 1077833728 (82.1%)
G1 Survivor Space memory used: 262128 (12.5%)
[0.905s] [info] [gc, start
] GC (2) Pause Young (Concurrent Start) (G1 Humongous Allocation)
[0.906s] [info] [gc, task [0.907s] [info] [gc, phases
1 GC(2) Using 8 workers of 8 for evacuation
1 GC (21
[0.907s] [info] [g, phases
GC (2)
Merge Heap Roots: 0.1ms
[0.907s] [info] [gc, phases
GC (2)
Evacuate Collection Set: 0.4ms
[0.907s] [info] [gc, phases
GC (2)
Post Evacuate Collection Set: 0.3ms
[0.907s] [info] [gc, phases
] GC (2)
Other: 0.3ms
[0.907s] [info] [gc, heap
] GC (2) Eden regions: 1->0 (32)
[0.907s] [info] [gc, heap
GC(2) Survivor regions: 1->1(2)
[0.907s] [info] [gc, heap
GC (2) Old regions: 0->0
[0.907s] [info] [gc, heap
] GC (2) ArchIve regIOnS: 2->2
[0.907s] [infol [gc, heap
] GC (2) Humongous regions: 513->513
[0.907s] [info] [g, metaspace] GC(2) Metaspace: 705K(896K)->705K (396K) NonClass: 637K(768K)->637K(768K) Class: 68K(128K) ->68K(128K)
[0.907s] [infol [ac
GC (2)
Pause Young (Concurrent Start) (G1 Humongous Allocation) 1029M->1028M(1284M) 1.180ms
Here are the details of my situation:
-
I have a Java program that is experiencing humongous allocations.
-
I am familiar with using GC logs to monitor these allocations and regions.
Is there any way to print out or monitor humongous allocations and regions in a Java program without using the GC logs? Any APIs or techniques that can provide this information programmatically would be greatly appreciated.
Thank You
dhanush427 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
3
You can use JFR Event Streaming API to handle jdk.ObjectAllocationOutsideTLAB
events programmatically. Allocations larger than a half of the heap region size are known to be humongous.
Here is an example:
import com.sun.management.HotSpotDiagnosticMXBean;
import jdk.jfr.consumer.RecordingStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.management.ManagementFactory;
import java.util.concurrent.ThreadLocalRandom;
public class HumongousAlloc {
private static long getRegionSize() {
try {
HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
ManagementFactory.getPlatformMBeanServer(),
"com.sun.management:type=HotSpotDiagnostic",
HotSpotDiagnosticMXBean.class);
return Long.parseLong(bean.getVMOption("G1HeapRegionSize").getValue());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private static void handleAllocations() {
long humongousAllocationSize = getRegionSize() / 2;
try (var rs = new RecordingStream()) {
rs.enable("jdk.ObjectAllocationOutsideTLAB");
rs.onEvent("jdk.ObjectAllocationOutsideTLAB", event -> {
long allocationSize = event.getValue("allocationSize");
if (allocationSize >= humongousAllocationSize) {
System.out.println("Humongous allocation: " + event);
}
});
rs.start();
}
}
static volatile Object sink;
public static void main(String[] args) {
new Thread(HumongousAlloc::handleAllocations).start();
while (true) {
int size = 1 << ThreadLocalRandom.current().nextInt(24);
sink = new byte[size];
}
}
}