如何使用 JNI+JVMTI 捕获 JIT 的反优化事件,例如 "unstable_if"

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

我确实了解如何捕获 JIT 的取消优化事件。
今天,我读了 Andrei Pangin 的精彩回答 并再次考虑了它。

我想用 JNI+JVMTI 捕获 JIT 的反优化事件,如“unstable_if、class_check 等”,然后将警报发送到我的监控系统或其他任何东西。

可能吗? 它对性能 JVM 有何影响?

不常见的陷阱和反优化是 HotSpot 的实现细节。您不会在像 JVM TI 那样的 标准 界面中找到它们(它是为通用虚拟机设计的,而不仅仅是 HotSpot)。

正如我在 中所建议的,诊断去优化的一种可能方法是添加 -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation 选项并在编译日志中查找 <uncommon_trap>

另一种方法是使用 async-profiler.
跟踪去优化事件 为此,请使用 -e Deoptimization::uncommon_trap_inner.
如果使用 jfr 输出格式,这将向您显示 Java 代码中发生去优化的位置,以及时间戳。

自 JDK 14 起,取消优化事件也由 Flight Recorder (JDK-8216041) 本机报告。使用JMC中的Event Browser,您可能会发现所有不常见的陷阱,包括方法名、字节码索引、反优化原因等

以上所有方法的开销都足够小。在生产中使用 async-profiler 通常没有问题; JFR也可以,如果录音设置不是多余的话

但是,除非常特殊的情况外,分析反优化没有多大用处。对于典型的 Java 应用程序来说,多次重新编译方法是绝对正常的,只要 JVM 在运行时了解更多关于应用程序的信息。听起来可能很奇怪,但不常见的陷阱是推测优化的常用技术:) 正如你在上面的图片中看到的,即使是像 HashMap.put 这样的基本方法也可能导致反优化,这很好。

从 JDK14(基于 OpenJDK)开始,您可以使用 Event Steaming API 以编程方式访问去优化事件。本地没有API。

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();