性能差距是在nextValue()方法的内联与否上
我自己测试的时候有一个有趣的发现:
使用 OpenJDK 15.0.2 的话,其实 static 与 non-static 性能差距是没有 11.0.2 上那么大的
# 均为5次运行取中位数
# OpenJDK 15.0.2
Cost of static example: 16ms
Cost of non-static example: 3ms
# OpenJDK 14
Cost of static example: 21ms
Cost of non-static example: 3ms
# OpenJDK 11.0.2
Cost of static example: 694ms
Cost of non-static example: 2ms
使用 OpenJDK 15.0.2 进行分析的话,可以看到在 15.0.2 上,Static版本的 nextValue() 和 11.0.2 上一样也是无法内联的。
miigon$ java -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining Main | grep nextValue
     34   35       3       StaticExample::nextValue (21 bytes)
     34   36       4       StaticExample::nextValue (21 bytes)
     35   35       3       StaticExample::nextValue (21 bytes)   made not entrant
                              @ 28   StaticExample::nextValue (21 bytes)   not inlineable  #这里
                              @ 28   StaticExample::nextValue (21 bytes)   not inlineable
     80  121       3       NonStaticExample::nextValue (10 bytes)
     80  122       4       NonStaticExample::nextValue (10 bytes)
     81  121       3       NonStaticExample::nextValue (10 bytes)   made not entrant
                              @ 47   NonStaticExample::nextValue (10 bytes)   inline
                              @ 47   NonStaticExample::nextValue (10 bytes)   inline
不理解 15.0.2 是如何做到不内联也性能差别如此小,个人猜测有可能是:11.0.2 上的 static 版本内不仅 nextValue() 没有内联,或许整个 static 代码块都没有 JIT 编译就执行了,而 15.0.2 上可能有对 static 代码块进行 JIT。不过这个没有 profile 的话也只是猜测。