JVM底层原理之JIT编译器如何通过方法内联优化代码
可能我们对JIT是如何将字节码编译成机器码的过程没多少兴趣 , 但是我们可以学习一下它采用了哪些优化技术和手段 , 毕竟它不仅是简单的进行编译 , 还进行了很多优化的操作 。
①方法内联方法内联介绍:
调用一个方法通常要经历压栈和出栈 , 如果当前执行的方法又调用了其他方法 , 就会加大时间和空间的开销 。 因为如果我们是在方法1的执行途中调用方法2 , 就需要将程序执行顺序转移到方法2的内存地址 , 将方法2的内容执行完后 , 再返回到方法1的位置继续执行 。 而这需要在执行方法2前 , 保存好执行到一半的方法1地址和环境 , 以便执行完方法2后进行恢复现场的工作(可以理解为一种上下文切换的精简版) 。
如果一层一层的下去 , 每层都是一笔开销 , 而如果我们将方法2的全部代码复制到方法1进行调用的地方 , 这样在调用方法1时 , 代码的逻辑没有任何改变 , 但是却不需要花费嵌套调用的开销了 , 这就是方法内联 。
代码举例:
首先 , 编译器读取的是字节码.class文件 , 当然是不可能读取java文件的 , 但是这里我还是用java代码举了个例子 , 主要是方便大家理解的是这么个意思的 。
进行方法内联前:
//方法1private int test(int x int y) { int result=add(xy);\t\treturn result;
//方法2private int add(int s1 int s2) {\t\treturn s1+s2;
\t
方法内联后:
private int test(int x int y) { int result=x+y;\t\treturn result;
参数调整:
方法内联不是百分百会被执行的 , 它会参考方法调用层数 , 目标方法的调用次数及字节码大小进行判断 , 我们也可以通过一些参数调整这个优化技术 。
说实话我不怎么喜欢贴参数配置 , 因为80%的人是不需要修改这些配置的 , 剩下20%在需要修改时会自己去百度 。。。 而且还要付出自己瞎JB改虚拟机参数的代价(大佬除外) 。 所以这里主要看看我们可以定制哪些参数就行了 , 不用记参数指令 。
- 如果方法是经常执行的 , 方法小于325字节的会进行内联优化 , 可以用参数
-XX:MaxFreqInlineSize=N
调整这个字节大小 。
- 如果方法不经常执行 , 方法小于35字节才会进行内联优化 。 可以用参数
-XX:MaxInlineSize=N
调整这个字节大小 。
- -XX:CompileCommand配置中的inline指令指定的方法会被强制内联 , dontinline和exclude指定的方法始终不会被内联
- @ForceInline注解的jdk内部方法会被强制内联 , @DontInline注解jdk内部方法始终不会被内联
- 方法的符号引用未被解析、目标方法所在类未被初始化、或目标方法是native方法 , 都会导致方法无法内联
- C2默认不支持9层以上的方法调用(可通过
-XX:MaxInlineLevel
调整) , 以及1层的直接递归调用(可通过-XX:MaxRecursiveInlineLevel
调整)
- jvm|有人把天玑9000吹过头了
- jvm|JVM底层原理之如何选用C1、C2编译器?它们有什么区别?
- jvm|小米推出具有惊人功能的8H手感皮革智能电动床X Pro
- jvm|五一准备换电脑?恰好神舟战神笔记本也放“价”
- jvm|OPPO K10、OPPO K10 Pro怎么选?一文带你详细了解
- jvm|3199的OPPOK10Pro对比2499的K10,差价是由哪些东西带来的?
- jvm|那款一抬腕,就知前方路线的Apple Watch你有了吗?
- jvm|卢伟冰预热Redmi Note 12,性能强悍,价格良心,值得期待!
- jvm|佳能相机在全画微单时代的情况
- jvm|扎克伯格坐拥千亿,上厕所都带好几个保镖,一件上衣价值上万元