我一直在思考如何捕捉JIT的去优化事件。
今天,我读到了Andrei 当繁忙的java线程被绑定到物理内核时,上下文切换会因为到达代码中的新分支而发生吗?的精彩答案,并重新思考了一下。
我想用unstable_if、class_check等JNI+JVMTI捕捉JIT的去优化事件,然后向我的监控系统或其他任何东西发送警报。
有可能吗?它对性能JVM有什么影响?
发布于 2020-10-19 11:41:47
不常见的陷阱和去优化是HotSpot实现细节。您不会在像JVM TI这样的标准接口中找到它们(这是为通用虚拟机设计的,而不仅仅是HotSpot)。
正如我的先前的回答中所建议的,诊断去优化的一种可能方法是添加-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation选项并在编译日志中查找<uncommon_trap>。
另一种方法是使用异步分析器跟踪去优化事件。
要做到这一点,请使用-e Deoptimization::uncommon_trap_inner。
如果使用jfr输出格式,这将向您展示Java代码中发生去优化的地方,以及时间戳。

自JDK 14以来,飞行记录器(JDK-8216041)也本机报告了去优化事件。使用JMC中的事件浏览器,您可能会发现所有不常见的陷阱,包括方法名称、字节码索引、去优化原因等。

上述所有方法的开销都足够小。在生产中使用异步分析器通常没有问题;如果记录设置不是多余的,JFR也很好。
但是,除了非常特殊的情况外,在分析去优化方面没有多大用处。对于一个典型的Java应用程序来说,只要JVM在运行时了解更多关于应用程序的信息,就可以多次重新编译方法,这是绝对正常的。这听起来可能很奇怪,但不常见的陷阱是一种常见的投机优化技术:)正如您在上面的图片中所看到的,即使是HashMap.put这样的基本方法也可能导致去优化,这是很好的。
发布于 2020-10-19 16:51:05
从JDK 14 (基于OpenJDK),您可以使用事件蒸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();https://stackoverflow.com/questions/64424775
复制相似问题