java虚拟机(九)编译是如何优化代码的

首先我们要明白优化代码,并不是建立在java的源码之上的。而是建立在代码的中间表达是或者机器码上面。

公共子表达式消除

如果一个表达式E已经出现过了。而且下面出现的E的所有变量值都没有发生改变,那就可以优化。

如  a=b*c+r+c*b

这里b*c和c*b是一样的。所以可以变成 a=e+r+e

数组边界检查消除

我们知道java是一门动态安全的语言。访问数组的时候,会进行上下界限的检查。是否每一次都真的有必要检查呢?

其实,只要在编译的时候根据数组的大小来判断是否出界就行了。 特别是循环数组的时候,只要区间一直在0到数组最大下标直接。在编译是判断。那么在运行期间就不必去检查。

方法内联

它是编译器最重要的优化手段之一。方法内联后,其他方法才能基于它。

我们知道,调用其他方法要有出栈入栈等操作。影响效率。但是如果把这个方法放到代码当中,那就不用调用。当然就会快。

但是,这是非虚方法才好。(非虚方法在编译的时候就可以知道是哪个方法,如私有方法,静态方法等)。

内联后,还有一个逃生门,因为你虚拟机不知道这个方法的接受者的继承关系会发生变化。也就是说,这个方法可能不是惟一的。那就抛弃已经编译的代码,退回到解释状态。

虚方法,有个内联缓存。调用到这个方法的哪个具体实现,那就存这个。

逃逸分析

如果一个对象会被外部方法调用,那就叫做方法逃逸

如果一个对象会被其他的线程访问到,那就叫做线程逃逸

栈上分配 

一个对象不会方法逃逸和线程逃逸,那就一个把对象分配到栈上。我们知道,垃圾回收的效率是比较缓慢的。但是如果对象能随着方法的结束而自动销毁。那垃圾回收压力就会小很多

同步消除

线程的同步是一个相对耗时的过程。如果如果一个对象没有线程逃逸,那就可以关掉线程同步。

标量替换

标量是值无法在分解的数据。如int long 等。如果一个对象不会方法逃逸,而且这个对象可以被拆散的话。我们用到他的成员变量就不用再调用对象的成员变量。直接替换为相应的标量。

发布了82 篇原创文章 · 获赞 49 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/xu505928168/article/details/98984575