JVM会自动的识别热点方法,并对它们使用方法内联优化。那么一段代码需要执行多少次才会触发JIT优化呢?通常这个值由-XX:CompileThreshold参数进行设置:
使用client编译器时,默认为1500;
使用server编译器时,默认为10000;
但是一个方法就算被JVM标注成为热点方法,JVM仍然不一定会对它做方法内联优化。其中有个比较常见的原因就是这个方法体太大了,分为两种情况。
如果方法是经常执行的,默认情况下,方法大小小于325字节的都会进行内联(可以通过** -XX:MaxFreqInlineSize=N**来设置这个大小)
如果方法不是经常执行的,默认情况下,方法大小小于35字节才会进行内联(可以通过** -XX:MaxInlineSize=N **来设置这个大小)
我们可以通过增加这个大小,以便更多的方法可以进行内联;但是除非能够显著提升性能,否则不推荐修改这个参数。因为更大的方法体会导致代码内存占用更多,更少的热点方法会被缓存,最终的效果不一定好。
JVM参数:(-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining)
触发方法内联的规则
自动拆箱总被内联;
-XX:CompileCommand中的inline指令指定的方法;
@ForceInline注解的方法;
不触发方法内联的规则
Throwable类的方法不能被其他类中的方法内联;
-XX:CompileCommand中dotinline或exclude指令指定的方法;
@Dontinline注解的方法;
调用字节码对应的符号引用未被解析;
目标方法所在的类未被初始化;
目标方法是native方法;
C2不支持内联超过9层的调用(-XX:MaxInlineLevel),以及1层的直接递归调用(-XX:MaxRecursIninleLevel)
假如你了解java的函数跳转中栈帧的变化并且需要开启关闭一个新的操作数栈,那么当我们编写一个新的方法提取一个方法并且这个方法执行的操作是非常少的,南无这个方法跳转就是耗费性能的。jvm运行期会对其进行优化,而我们在开发中也要有这个意识,让jvm帮我们优化那岂不是很low?
网友评论