有没有一种轻量级的方法可以在Java 9+中添加安全点 [英] Is there a lightweight method which adds a safepoint in Java 9+

查看:78
本文介绍了有没有一种轻量级的方法可以在Java 9+中添加安全点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java 9+中是否有更便宜的方法调用来保持其安全点?

Is there a cheaper method call in Java 9+ which keeps its safepoint?

JVM会在运行时删除安全点以提高效率,但是这可能使概要分析和监视代码更加困难.因此,我们特意在精心选择的地方添加了一些琐碎的电话,以确保存在安全点.

The JVM removes safepoints at runtime to improve efficiency however this can make profiling and monitoring the code more difficult. For this reason, we deliberately add trivial calls in carefully selected places to ensure there is a safepoint present.

public static void safepoint() {
    if (IS_JAVA_9_PLUS)
        Thread.holdsLock(""); // 100 ns on Java 11
    else
        Compiler.enable(); // 5 ns on Java 8
}

public static void optionalSafepoint() {
    if (SAFEPOINT_ENABLED)
        if (IS_JAVA_9_PLUS)
            Thread.holdsLock("");
        else
            Compiler.enable();
}

在Java 8上,这种开销是可以的,但是Compiler.enable()在Java 9+中得到了优化,因此我们必须使用更昂贵的方法,或者不启用此功能.

On Java 8 this overhead is fine, but Compiler.enable() gets optimised away in Java 9+ so we have to use a much more expensive method, or not enable this feature.

除了分析器外,我还使用safepoint()Thread.getStackTrace()中获得了更好的详细信息,因此应用程序可以对自身进行分析,例如当执行动作所需的时间太长时.

Apart from profilers, I have used the safepoint() to get better detail from Thread.getStackTrace() so the application can profile itself e.g. when it takes too long to perform an action.

推荐答案

在HotSpot JVM中,安全点(JVM可以安全地停止Java线程的位置)是

In HotSpot JVM, safepoints (where the JVM can safely stop Java threads) are

  • 从非内联方法返回之前;
  • 在向后分支(即循环)中,除非计算了循环.如果已知迭代次数有限,并且循环变量适合整数类型,则对循环进行计数;
  • 在线程状态转换时(本机-> Java,本机-> VM);
  • 在JVM运行时的阻止功能中.

以上所有地方,除了向后分支,都意味着至少有一个方法调用开销.因此,放置安全点的最便宜的方法显然是编写一个非计数循环:

All the above places, except backward branches, imply at least a method call overhead. So, apparently the cheapest way to put a safepoint is to write a non-counted loop:

public class Safepoint {
    private static volatile int one = 1;

    public static void force() {
        for (int i = 0; i < one; i++) ;
    }
}

volatile保证优化器不会消除该循环,也不会将其视为已计数.

volatile guarantees that the loop will not be eliminated by the optimizer, and it will not be treated as counted.

我用-XX:+PrintAssembly验证了在我调用Safepoint.force()的任何地方都插入了安全点轮询指令.通话本身大约需要1 ns.

I verified with -XX:+PrintAssembly that the safepoint poll instruction is inserted wherever I call Safepoint.force(). The call itself takes about 1 ns.

但是,由于JDK 8中的错误,安全点轮询的存在尚不能保证从其他线程获得的堆栈跟踪的正确性.本地方法调用设置了最后一个Java框架锚,因此对它进行修复".堆栈跟踪.我想这就是您选择本机方法的原因.该错误已在JDK 9+中修复.

However, due to a bug in JDK 8, the existence of safepoint polls does not yet guarantee the correctness of stack traces obtained from a different thread. A native method call sets the last Java frame anchor, and thus "repairs" the stack trace. I guess this was a reason why you chose a native method. The bug was fixed in JDK 9+ though.

顺便说一句,这是一些本机方法,其开销比Thread.holdsLock低:

BTW, here is a couple of native methods that have lower overhead than Thread.holdsLock:

Thread.currentThread().isAlive()
Runtime.getRuntime().totalMemory()

关于分析,基于安全点的探查器为一开始完全被破坏.这实际上是几年前我开始 async-profiler 项目的原因.其目标是以低开销且无安全点偏差的方式促进对Java应用程序的性能分析.

As to profiling, the safepoint-based profilers are completely broken in the first place. This is actually a reason why I started async-profiler project a few years ago. Its goal is to facilitate profiling of Java applications with low overhead and with no safepoint bias.

这篇关于有没有一种轻量级的方法可以在Java 9+中添加安全点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆