java9内在方法不清楚

Eug*_*ene 8 java jvm virtual-machine jvm-arguments java-9

假设我有这个代码(我认为这无关紧要,但以防万一):

public class AtomicJDK9 {

     static AtomicInteger ai = new AtomicInteger(0);

     public static void main(String[] args) {
        int sum = 0;
        for (int i = 0; i < 30_000; ++i) {
           sum += atomicIncrement();
        }
        System.out.println(sum);
     }

     public static int atomicIncrement() {
         ai.getAndAdd(12);
         return ai.get();
     }
}
Run Code Online (Sandbox Code Playgroud)

以下是我如何调用它(使用java-9):

 java -XX:+UnlockDiagnosticVMOptions 
      -XX:-TieredCompilation  
      -XX:+PrintIntrinsics  
      AtomicJDK9
Run Code Online (Sandbox Code Playgroud)

我想要找出的是什么方法被内在代码所取代.第一个被击中(在不安全的内部):

      @HotSpotIntrinsicCandidate
      public final int getAndAddInt(Object o, long offset, int delta) {
         int v;
         do {
            v = getIntVolatile(o, offset);
         } while (!weakCompareAndSwapIntVolatile(o, offset, v, v + delta));
         return v;
      }
Run Code Online (Sandbox Code Playgroud)

并且这个方法确实存在于上面调用的输出中:

 @ 8   jdk.internal.misc.Unsafe::getAndAddInt (27 bytes)   (intrinsic)
Run Code Online (Sandbox Code Playgroud)

但是,整个输出很奇怪(对我而言):

 @ 8   jdk.internal.misc.Unsafe::getAndAddInt (27 bytes)   (intrinsic)
 @ 3   jdk.internal.misc.Unsafe::getIntVolatile (0 bytes)   (intrinsic)
 @ 18  jdk.internal.misc.Unsafe::weakCompareAndSwapIntVolatile (11 bytes)   (intrinsic)
 @ 7   jdk.internal.misc.Unsafe::compareAndSwapInt (0 bytes)   (intrinsic)
 @ 8   jdk.internal.misc.Unsafe::getAndAddInt (27 bytes)   (intrinsic)
Run Code Online (Sandbox Code Playgroud)

为什么getAndAddInt在输出中出现两次?

此外,如果getAndAddInt确实被内部调用替换,为什么需要在调用堆栈中替换所有其他内部方法 l它们将不再被使用.我认为它就像从底部遍历方法调用的堆栈一样简单.

apa*_*gin 7

为了说明编译器逻辑,我使用以下参数运行JVM.

    -XX:-TieredCompilation -XX:CICompilerCount=1
    -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining 
Run Code Online (Sandbox Code Playgroud)

这就是它打印的内容.

337   29   java.util.concurrent.atomic.AtomicInteger::getAndAdd (12 bytes)
              @ 8   jdk.internal.misc.Unsafe::getAndAddInt (27 bytes)   (intrinsic)
337   30   jdk.internal.misc.Unsafe::getAndAddInt (27 bytes)
              @ 3   jdk.internal.misc.Unsafe::getIntVolatile (0 bytes)   (intrinsic)
              @ 18   jdk.internal.misc.Unsafe::weakCompareAndSwapIntVolatile (11 bytes)   (intrinsic)
338   32   jdk.internal.misc.Unsafe::weakCompareAndSwapIntVolatile (11 bytes)
              @ 7   jdk.internal.misc.Unsafe::compareAndSwapInt (0 bytes)   (intrinsic)
339   33   AtomicJDK9::atomicIncrement (16 bytes)
              @ 5   java.util.concurrent.atomic.AtomicInteger::getAndAdd (12 bytes)   inline (hot)
                @ 8   jdk.internal.misc.Unsafe::getAndAddInt (27 bytes)   (intrinsic)
              @ 12   java.util.concurrent.atomic.AtomicInteger::get (5 bytes)   accessor
Run Code Online (Sandbox Code Playgroud)
  • 方法只是编译器的内在函数,但不适用于解释器.
  • 每个方法都从解释器开始,直到被认为是热门.
  • AtomicInteger.getAndAdd 不仅从您的代码调用,而且从常见的JDK代码调用.
  • 也就是说,AtomicInteger.getAndAdd达到调用阈值比你的早一点AtomicJDK9.atomicIncrement.然后getAndAdd提交到编译队列,这是第一个内在打印输出的来源.
  • HotSpot JVM在后台编译方法.在编译方法时,执行在解释器中继续.
  • 虽然AtomicInteger.getAndAdd被解释,Unsafe.getAndAddIntUnsafe.weakCompareAndSwapIntVolatile方法也达到调用门槛,并开始编制.在编译这些Unsafe方法时会打印下3个内在函数.
  • 最后,AtomicJDK9.atomicIncrement也到达调用threashold并开始编译.最后一个内在打印输出对应于您的方法.