Java 运行时优化
1. 逃逸分析
概念:判断新建的对象是否逃逸,可以使用 -XX:-DoEscapeAnalysis 关闭逃逸分析。
逃逸分析利用的是JVM分层编译,JVM的执行状态分为五个层次:
即时编译器比起解释器多了Code Cache,下次遇到相同的代码直接执行不需要再编译,所以执行后面重复代码会更快。
2. 方法内联
如果发现一个方法是热点方法,并且长度不太长时,会进行内联,所谓的内联就是把方法内代码拷贝、粘贴到调用者的位置;
C++有显式的inline关键字。
3. 成员变量读取优化
public void test1() {//只要不禁用方法内联,JVM会帮我们优化,只读一次elements.length for (int i = 0; i < elements.length; i++) { doSum(elements[i]); } } public void test2() {//手动优化成局部变量,只读取一次成员变量elements int[] local = this.elements; for (int i = 0; i < local.length; i++) { doSum(local[i]); } } public void test3() {//foreach也会优化,等价于test2 for (int element : elements) { doSum(element); } }
4. 反射优化
public class Reflect1 { public static void foo() { System.out.println("foo..."); } public static void main(String[] args) throws Exception { Method foo = Reflect1.class.getMethod("foo"); for (int i = 0; i <= 16; i++) { System.out.printf("%d\t", i); foo.invoke(null); } System.in.read(); } }
foo.invoke 前面 0 ~ 15 次调用使用的是 MethodAccessor 的 NativeMethodAccessorImpl 实现(性能较低),当调用到第 16 次(从0开始算)时,会采用运行时生成的类代替掉最初的实现(性能变高)
通过debug可以看到这个类叫sun.reflect.GeneratedMethodAccessor1,它里面实现的就是直接调用方法foo而不是反射调用