I just wondered if there's a way to detect a Garbage Collection cycle from within the code/JVM that's being gc'd.
Timing does not play a role. So whether it's an event that occurs sometime before the actual cycle or afterwards is not important. (Having an event DURING the cycle seems highly unlikely and is probably dangerous too, depending on the GC implementation used).
All I could find were apps that can be used in parallel to the running JVM, such as jstat: https://dzone.com/articles/how-monitor-java-garbage with the source code here, for example: https://github.com/eagle518/jdk-source-code/blob/master/jdk5.0_src/j2se/src/share/classes/sun/tools/jstat/Jstat.java
All I see is that they use
MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId);
MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, interval);
So my problem is based on 2 questions. If the second question has a solution, we don't need to answer Q 1:
MonitoredVm
?Runtime.getRuntime().addShutdownHook(hookThread);
)? Java Reflection is also a welcome solution!GarbageCollectorMXBean
is pointing into the right direction. What’s not obvious, is that this bean implements NotificationEmitter
which allows notifications about garbage collections:
static volatile Object PREVENT_ESCAPE_ANALYSIS;
public static void main(String[] args) {
List<GarbageCollectorMXBean> gc = ManagementFactory.getGarbageCollectorMXBeans();
for(GarbageCollectorMXBean b: gc) {
((NotificationEmitter)b).addNotificationListener((n, handback) -> {
GarbageCollectionNotificationInfo gcni
= GarbageCollectionNotificationInfo.from((CompositeData)n.getUserData());
GcInfo info = gcni.getGcInfo();
System.out.printf("%tT.%1$tL %dms %s %s %s%n", info.getStartTime(),
info.getDuration(),gcni.getGcName(),gcni.getGcAction(),gcni.getGcCause());
Map<String, MemoryUsage> before = info.getMemoryUsageBeforeGc();
info.getMemoryUsageAfterGc().forEach((s, u) -> {
long bu = before.get(s).getUsed(), au = u.getUsed();
if(bu != au) System.out.println("\t" + s + " " + bu + " -> " + au);
});
}, null, b);
}
for(;;) {
PREVENT_ESCAPE_ANALYSIS = new Object();
}
}
00:00:00.203 2ms Copy end of minor GC Allocation Failure
Eden Space 70516736 -> 0
Survivor Space 0 -> 795176
00:00:00.271 1ms Copy end of minor GC Allocation Failure
Eden Space 70516736 -> 0
Survivor Space 795176 -> 862960
00:00:00.355 2ms Copy end of minor GC Allocation Failure
Eden Space 70516736 -> 0
Survivor Space 862960 -> 931952
00:00:00.412 2ms Copy end of minor GC Allocation Failure
Eden Space 70516736 -> 0
Survivor Space 931952 -> 1004784
00:00:00.497 2ms Copy end of minor GC Allocation Failure
Eden Space 70516736 -> 0
Survivor Space 1004784 -> 1379400
00:00:00.574 3ms Copy end of minor GC Allocation Failure
Eden Space 70516736 -> 0
Survivor Space 1379400 -> 1551944
00:00:00.632 2ms Copy end of minor GC Allocation Failure
Eden Space 70516736 -> 0
Survivor Space 1551944 -> 1541144
…