假设我有这个代码(我认为这无关紧要,但以防万一):
brew install coreutils
brew install binutils
brew install diffutils
brew install ed --with-default-names
brew install findutils --with-default-names
brew install gawk
brew install gnu-indent --with-default-names
brew install gnu-sed --with-default-names
brew install gnu-tar --with-default-names
brew install gnu-which --with-default-names
brew install gnutls
brew install grep --with-default-names
brew install gzip
brew install screen
brew install watch
brew install wdiff --with-gettext
brew install wget
brew install bash
brew install emacs
brew install gdb
brew install gpatch
brew install less
brew install m4
brew install make
brew install nano
brew install file-formula
brew install git
brew install openssh
brew install perl
brew install python
brew install rsync
brew install svn
brew install unzip
brew install vim --override-system-vi
brew install macvim --override-system-vim --custom-system-icons
brew install zsh
sudo launchctl config user path /usr/local/opt/coreutils/libexec/gnuman:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Library/TeX/texbin
以下是我如何调用它(使用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();
}
}
我想知道的是什么方法被内在代码所取代。第一个被击中(在不安全的地方):
java -XX:+UnlockDiagnosticVMOptions
-XX:-TieredCompilation
-XX:+PrintIntrinsics
AtomicJDK9
此方法确实存在于上述调用的输出中:
@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;
}
但是,整个输出很奇怪(对我而言):
@ 8 jdk.internal.misc.Unsafe::getAndAddInt (27 bytes) (intrinsic)
为什么 getAndAddInt 在输出中出现两次?
如果getAndAddInt确实被内部调用替换,为什么需要在调用堆栈中替换所有其他内部方法 l它们将不再被使用。我认为这很简单,因为方法调用的堆栈是从底部遍历的。
答案 0 :(得分:7)
为了说明编译器逻辑,我使用以下参数运行JVM。
-XX:-TieredCompilation -XX:CICompilerCount=1
-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining
这就是打印的内容。
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
AtomicInteger.getAndAdd
不仅可以从您的代码中调用,还可以从常见的JDK代码中调用。AtomicInteger.getAndAdd
比AtomicJDK9.atomicIncrement
早一点达到调用阈值。然后getAndAdd
被提交到编译队列,这就是第一个内在打印输出的来源。AtomicInteger.getAndAdd
时,Unsafe.getAndAddInt
和Unsafe.weakCompareAndSwapIntVolatile
方法也会达到调用阈值并开始编译。在编译这些Unsafe
方法时会打印下3个内在函数。AtomicJDK9.atomicIncrement
也到达调用threashold并开始编译。最后一个内在打印输出对应于您的方法。