JVM底层原理之JIT编译器如何通过方法内联优化代码
可能我们对JIT是如何将字节码编译成机器码的过程没多少兴趣 , 但是我们可以学习一下它采用了哪些优化技术和手段 , 毕竟它不仅是简单的进行编译 , 还进行了很多优化的操作 。
①方法内联方法内联介绍:
调用一个方法通常要经历压栈和出栈 , 如果当前执行的方法又调用了其他方法 , 就会加大时间和空间的开销 。 因为如果我们是在方法1的执行途中调用方法2 , 就需要将程序执行顺序转移到方法2的内存地址 , 将方法2的内容执行完后 , 再返回到方法1的位置继续执行 。 而这需要在执行方法2前 , 保存好执行到一半的方法1地址和环境 , 以便执行完方法2后进行恢复现场的工作(可以理解为一种上下文切换的精简版) 。
如果一层一层的下去 , 每层都是一笔开销 , 而如果我们将方法2的全部代码复制到方法1进行调用的地方 , 这样在调用方法1时 , 代码的逻辑没有任何改变 , 但是却不需要花费嵌套调用的开销了 , 这就是方法内联 。
【jvm|JVM底层原理之JIT编译器如何通过方法内联优化代码】代码举例:
首先 , 编译器读取的是字节码.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底层原理之HotSpotVM的热点探测机制
- jvm|一百元左右的蓝牙耳机多如牛毛,真正听音乐表现不错的屈指可数!
- 流媒体|JVM底层原理之热点代码和HotSpotVM的运行流程
- |为什么引流推广没有效果?这就是引流的底层逻辑,千万别错过
- VR|社区团购为什么会全线溃败?为你揭秘社群营销的底层逻辑
- jvm|JVM底层原理之什么是分层编译?
- jvm|JVM底层原理之如何选用C1、C2编译器?它们有什么区别?
- jvm|美国资本的无序扩张严重威胁世界了
- jvm|vivo X80对比红米K50 Pro反应速度,堪称棋逢对手!
- 工业互联网|自媒体的底层逻辑