逃逸分析

逃逸分析(Escape Analysis)的基本原理是:分析对象动态作用域,当一个对象在方法里面

被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他方法中,这种称为方法逃逸。

甚至可能被外部线程访问到,譬如赋值给可以在其他线程中访问的实例变量,这种称为线程逃逸。

利用逃离分析进行优化

栈上分配(Stack Allocations)

如果确定一个对象不会逃逸到线程之外,那可以让这个对象在栈上分配内存,对象占用的内存空间

就可以随栈桢出栈而销毁。栈上分配可以支持方法逃逸,但不能支持线程逃逸。

标量替换(Scalar Replacement)

若一个数据已经无法再分解成更小的数据来表示(如Java的基本类型,reference类型等),那么这些数据就可以被

称为标量。相对的,如果一个数据可以继续分解,那它就被称为聚变量(Aggregate,如Java对象)。

把一个Java对象拆散,根据程序访问的情况,将其用到的成员变量恢复为原始类型来访问,

这个过程就被称为标量替换。加入逃逸分析能够证明一个对象不会被方法外部访问,并且这个对象可以被拆散,

那么程序真正执行的时候将可能不去创建这个对象,而改为直接创建它的若干个被这个方法使用的成员变量来替代。

将对象拆分后除了可以让对象的成员变量在栈上,还可以为后续进一步优化手段创建条件。

标量替换可以视作栈上分配的一种特例,但对逃逸程度要求更高,不允许对象逃逸出方法范围内。

同步消除(Synchronization Elimination)

线程同步本身是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,无法被

其他线程访问,那么这个变量的读写肯定就不会有竞争,对这个变量的同步措施也就可以安全地

消除掉。

使用情况

JDK7逃逸分析才称为服务端编译器默认开启的选项。可以使用-XX:+DoEscapeAnalysis手动开启

逃逸分析,开启之后可以通过参数-XX:PrintEscapeAnalysis查看分析结果。开启逃逸分析之后,

可以使用-XX:+EliminateAllocations开启标量替换,使用-XX:EliminateLocks开启同步消除,

使用-XX:PrintEliminateAllcations查看标量替换情况。