How can I catch JIT's deoptimization events like "unstable_if" with JNI+JVMTI

975 Views Asked by At

I've realy though about how can I catch JIT's deoptimization events.
Today, I've read brilliant answer by Andrei Pangin When busy-spining java thread is bound to physical core, can context switch happen by the reason that new branch in code is reached? and thought about it again.

I want to catch JIT's deoptimization events like "unstable_if, class_check and etc" with JNI+JVMTI then send alert to my monitoring system or anything else.

Is it possible? What is it impact on performance JVM ?

2

There are 2 best solutions below

0
On BEST ANSWER

Uncommon traps and deoptimization are HotSpot implementation details. You won't find them in a standard interface like JVM TI (which is designed for a generic virtual machine, not just HotSpot).

As suggested in my previous answer, one possible way to diagnose deoptimization is to add -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation options and to look for <uncommon_trap> in the compilation log.

Another approach is to trace deoptimization events with async-profiler.
To do so, use -e Deoptimization::uncommon_trap_inner.
This will show you the places in Java code where deoptimization happens, and also timestamps, if using jfr output format.

Deoptimization: async-profiler

Since JDK 14, deoptimization events are also reported natively by Flight Recorder (JDK-8216041). Using Event Browser in JMC, you may find all uncommon traps, including method name, bytecode index, deoptimization reason, etc.

Deoptimization: JFR

The overhead of all the above approaches is small enough. There is usually no problem in using async-profiler in production; JFR is also fine, if the recording settings are not superfluous.

However, there is no much use in profiling deoptimizations, except for very special cases. This is absolutely normal for a typical Java application to recompile methods multiple times, as long as the JVM learns more about the application in runtime. It may sound weird, but uncommon traps is a common technique of the speculative optimization :) As you can see on the above pictures, even basic methods like HashMap.put may cause deoptimization, and this is fine.

0
On

From JDK 14 (based on OpenJDK) you can access deoptimization events programmatically using the Event Steaming API. There is no API from native.

import jdk.jfr.consumer.RecordingStream;

RecordingStream s = new RecordingStream();
s.enable("jdk.Deoptimization").withStackTrace();
s.onEvent("jdk.Deoptimization", e -> {
  System.out.println("Time: " + e.getEndTime());
  System.out.println("Reason: " + e.getString("reason"));
  System.out.println("Action: " + e.getString("action"));
  System.out.println("Instruction: "+ e.getString("instruction"));
  System.out.println("Line Number: " + e.getInt("lineNumber"));
  System.out.println("Bytecode Index" + e.getInt("bci"));
  RecordedMethod m = e.getValue("method");
  RecordedStackTrace st = e.getStackTrace();
  RecordedThread t = e.getThread();
  ...
});
s.start();