逃逸分析简单来讲就是,Java HotSpot虚拟机可以分析新创建对象的使用范围,并决定是否在Java堆上分配内存的一项技术。
先说结论,不一定,但是得看具体虚拟的实现方式。而Oracle Hotspot JVM中所有的对象就都是在堆上分配的。
然后来理解一下,这个问题问出来,就说明,对象可能不在堆上上分配,而这就利用到了逃逸分析这项技术。
就像前面定义所说,逃逸分析分析出来的结果,就是一个对象的逃逸状态,也就是该对象的使用范围。逃逸状态有三种
- 全局逃逸:对象从方法和线程中逃逸出去;比如对象是一个静态变量,对象作为当前方法的返回值,对象作为一个逃逸对象的字段等。
- 参数逃逸:一个对象被当作参数传递或者被参数引用,但是在方法调用的过程中不会发生全局逃逸。
- 没有逃逸:即方法中的对象没有逃逸,该对象的使用范围就在该方法中。
而通过上面的三种状态,可以对一些状态下的对象进行优化
锁消除
如果一个对象没有逃逸,就说明该对象只会被当前线程使用。一个线程当前只会运行一个方法,并且该变量只在该方法中被创建,并在方法执行结束后就不在使用。所以只有当前线程使用。那么对该对象进行的同步锁就没有意义。编译器可以优化移除掉这些锁操作
栈上分配(标量替换)
标量:基础类型和对象的引用可以理解为标量,他们不能被进一步分解 聚合量:对象。对象是聚合量,可以被进一步分解为标量。
标量替换就是讲一个聚合量分解替换为分散的标量。
如果一个对象没有发生逃逸,那么可以在栈上分配这些对象,和方法的生命周期一致,随着栈帧出栈时销毁,减少了 GC 压力,提高了应用程序性能。