JVM中逃逸分析、栈上分配和标量替换是三个比较重要的概念。最近对它们的理解比较模糊,因此总结一下。
1. 基本概念
逃逸分析:一种判断在某方法A中的对象,其作用域有没有超出方法A的技术。如果超出了,则称其逃逸成功,否则逃逸失败。
栈上分配:对于逃逸失败的对象,将其分配在栈上,而不是堆上的技术。该技术的目的在于减少堆空间中的对象数目,从而减少了GC的频率,能提升性能。
标量替换:仍然是对于逃逸失败的对象,将对象这个聚合量分为若干个标量(基本数据类型)储存在栈上的技术。
2. HotSpot虚拟机的实际状况
实现了逃逸分析和标量替换,但是没有实现栈上分配。
3. 如何理解三者的关系:
首先,逃逸分析是标量替换和栈上分配的基础,没有逃逸分析,后两者不可能成立。原因很简单,栈上分配和标量替换的目的都是减少堆区的数据,而堆区的数据可以被多个线程所访问。因此要想实现栈上分配和标量替换,我们必须保证被分配的对象只被一个线程所使用,否则在A线程中我们把对象栈上分配/标量替换了,然后A线程的方法结束后栈空间被回收,接下来B线程要想访问该对象的数据就报错了。
其次,HotSpot没有实现栈上分配是指没有实现“狭义上”的栈上分配。所谓“狭义上”的栈上分配,指的是在栈上,按照堆空间中的对象分配模式进行分配,即除了对象分配的位置有区别:一个在堆上,一个在栈上,其它分配的模式、方法没有任何区别。
但是HotSpot实现了“广义上”栈上分配,即它通过标量替换的方式,将逃逸失败的对象分解为标量存储在栈上,随着栈帧的弹出而被回收。因此仍然能达到我们