JVM解释和编译指南( 二 )

在这个程序的main方法中创建了一个Demo对象的实例,并调用该实例的square方法,然后显示for循环迭代变量的平方值 。编译并运行它:
$ javac Demo.java$ java Demo1 iterationSquare(i) = 1Time taken= 8432439--------------------------------2 iterationSquare(i) = 4Time taken= 54631--------------------------------...--------------------------------10 iterationSquare(i) = 100Time taken= 66498--------------------------------上面的结果是由谁产生的呢?是解释器,JIT 还是 AOT?在目前的情况下,它完全是通过解释产生的 。我是怎么得出这个结论的呢?只有代码被解释的次数必须超过某个阈值时,这些热点代码片段才会被加入 JIT 编译队列 。只有这时,JIT 编译才会发挥作用 。使用以下命令查看 JDK 11 中的该阈值:
$ java -XX:+PrintFlagsFinal -version | grep CompileThreshold intx CompileThreshold= 10000{pd product} {default}[...]openjdk version \"11.0.13\" 2021-10-19OpenJDK Runtime Environment 18.9 (build 11.0.13+8)OpenJDK 64-Bit Server VM 18.9 (build 11.0.13+8, mixed mode, sharing)上面的输出表明,一段代码被解释 10,000 次才符合 JIT 编译的条件 。这个阈值是否可以手动调整呢?是否有 JVM 标志可以指示出方法是否被 JIT 编译了呢?答案是肯定的,而且有多种方式可以达到这个目的 。
使用-XX:+PrintCompilation选项可以查看一个方法是否被 JIT 编译 。除此之外,使用
JVM解释和编译指南 。小编来告诉你更多相关信息 。
JVM解释和编译指南
-Xbatch标志可以提高输出的可读性 。如果解释和 JIT 同时发生,-Xbatch可以帮助区分两者的输出 。使用这些标志如下:
$ java -Xbatch-XX:+PrintCompilationDemo341b3java.util.concurrent.ConcurrentHashMap::tabAt (22 bytes)352n 0jdk.internal.misc.Unsafe::getObjectVolatile (native)353b3java.lang.Object::注意,上面命令的实际输出太长了,这里我只是截取了一部分 。输出很长的原因是除了Demo程序的代码外,JDK 内部类的函数也被编译了 。由于我的重点是Demo.java代码,我希望排除内部包的函数来简化输出 。通过选项-XX:CompileCommandFile可以禁用内部类的 JIT:
$ java -Xbatch -XX:+PrintCompilation -XX:CompileCommandFile=hotspot_compiler Demo在选项-XX:CompileCommandFile指定的文件hotspot_compiler中包含了要排除的包:
$ cat hotspot_compilerquietexclude java/* *exclude jdk/* *exclude sun/* *第一行的quiet告诉 JVM 不要输出任何关于被排除类的内容 。用-XX:CompileThreshold将 JIT 阈值设置为 5 。这意味着在解释 5 次之后,就会进行 JIT 编译:
$ java -Xbatch -XX:+PrintCompilation -XX:CompileCommandFile=hotspot_compiler \\-XX:CompileThreshold=5 Demo471n 0java.lang.invoke.MethodHandle::linkToStatic(LLLLLL)L (native)(static)472n 0java.lang.invoke.MethodHandle::invokeBasic(LLLLL)L (native)473n 0java.lang.invoke.MethodHandle::linkToSpecial(LLLLLLL)L (native)(static)484n 0java.lang.invoke.MethodHandle::linkToStatic(L)I (native)(static)485n 0java.lang.invoke.MethodHandle::invokeBasicI (native)486n 0java.lang.invoke.MethodHandle::linkToSpecial(LL)I (native)(static)[...]1 iteration6940n 0java.lang.invoke.MethodHandle::linkToStatic(ILIIL)I (native)(static)[...]Square(i) = 17848n 0java.lang.invoke.MethodHandle::linkToStatic(ILIJL)I (native)(static)7949n 0java.lang.invoke.MethodHandle::invokeBasic(ILIJ)I (native)[...]8654n 0java.lang.invoke.MethodHandle::invokeBasic(J)L (native)8755n 0java.lang.invoke.MethodHandle::linkToSpecial(LJL)L (native)(static)Time taken= 8962738--------------------------------2 iterationSquare(i) = 4Time taken= 26759--------------------------------10 iterationSquare(i) = 100Time taken= 26492--------------------------------好像输出结果跟只用解释时并没有什么区别 。根据 Oracle 的文档,这是因为只有禁用
JVM解释和编译指南 。小编来告诉你更多相关信息 。
JVM解释和编译指南
TieredCompilation-XX:CompileThreshold才会生效:
$ java -Xbatch -XX:+PrintCompilation -XX:CompileCommandFile=hotspot_compiler \\-XX:-TieredCompilation -XX:CompileThreshold=5 Demo1241njava.lang.invoke.MethodHandle::linkToStatic(LLLLLL)L (native)(static)1272njava.lang.invoke.MethodHandle::invokeBasic(LLLLL)L (native)[...]1 iteration18740njava.lang.invoke.MethodHandle::linkToStatic(ILIIL)I (native)(static)[...](native)(static)21254njava.lang.invoke.MethodHandle::invokeBasic(J)L (native)21255njava.lang.invoke.MethodHandle::linkToSpecial(LJL)L (native)(static)Time taken= 12337415[...]--------------------------------4 iterationSquare(i) = 16Time taken= 37183--------------------------------5 iteration21456bDemo::