首先我们要明白优化代码,并不是建立在java的源码之上的。而是建立在代码的中间表达是或者机器码上面。
公共子表达式消除
如果一个表达式E已经出现过了。而且下面出现的E的所有变量值都没有发生改变,那就可以优化。
如 a=b*c+r+c*b
这里b*c和c*b是一样的。所以可以变成 a=e+r+e
数组边界检查消除
我们知道java是一门动态安全的语言。访问数组的时候,会进行上下界限的检查。是否每一次都真的有必要检查呢?
其实,只要在编译的时候根据数组的大小来判断是否出界就行了。 特别是循环数组的时候,只要区间一直在0到数组最大下标直接。在编译是判断。那么在运行期间就不必去检查。
方法内联
它是编译器最重要的优化手段之一。方法内联后,其他方法才能基于它。
我们知道,调用其他方法要有出栈入栈等操作。影响效率。但是如果把这个方法放到代码当中,那就不用调用。当然就会快。
但是,这是非虚方法才好。(非虚方法在编译的时候就可以知道是哪个方法,如私有方法,静态方法等)。
内联后,还有一个逃生门,因为你虚拟机不知道这个方法的接受者的继承关系会发生变化。也就是说,这个方法可能不是惟一的。那就抛弃已经编译的代码,退回到解释状态。
虚方法,有个内联缓存。调用到这个方法的哪个具体实现,那就存这个。
逃逸分析
如果一个对象会被外部方法调用,那就叫做方法逃逸
如果一个对象会被其他的线程访问到,那就叫做线程逃逸
栈上分配
一个对象不会方法逃逸和线程逃逸,那就一个把对象分配到栈上。我们知道,垃圾回收的效率是比较缓慢的。但是如果对象能随着方法的结束而自动销毁。那垃圾回收压力就会小很多
同步消除
线程的同步是一个相对耗时的过程。如果如果一个对象没有线程逃逸,那就可以关掉线程同步。
标量替换
标量是值无法在分解的数据。如int long 等。如果一个对象不会方法逃逸,而且这个对象可以被拆散的话。我们用到他的成员变量就不用再调用对象的成员变量。直接替换为相应的标量。