栈上分配
虚拟机提供的一种优化技术,基本思想是,对于线程私有的对象,将它打散分配在栈上,而不分配在堆上。好处是对象跟着方法调用自行销毁,不需要进行垃圾回收,可以提高性能。
栈上分配需要的技术基础,逃逸分析。逃逸分析的目的是判断对象的作用域是否会逃逸出方法体。注意,任何可以在多个线程之间共享的对象,一定都属于逃逸对象。
//例1: public void test(int x, int y ){ String x = “”; User u = …. ….. } //User类型的对象u就没有逃逸出方法test。 //例2: public User test(int x, int y ){ String x = “”; User u = …. ….. return u; } //User类型的对象u就逃逸出方法test。
如何启用栈上分配
-server : JVM运行的模式之一, server模式才能进行逃逸分析, JVM运行的模式还有mix/client
-XX:+DoEscapeAnalysis:启用逃逸分析(默认打开)
-XX:+EliminateAllocations:标量替换(默认打开,加号代表开启,减号代表关闭)
对栈上分配发生影响的参数就是三个,-server、-XX:+DoEscapeAnalysis和-XX:+EliminateAllocations,任何一个发生变化都不会发生栈上分配,因为启用逃逸分析和标量替换默认是打开的,所以,在我们的例子中,JVM的参数只用-server一样可以有栈上替换的效果
标量替换
定义:通过逃逸分析确定该对象不会被外部访问,并且对象可以被进一步分解时,JVM不会创建该对象,而会将该对象成员变量分解若干个被这个方法使用的成员变量所代替。这些代替的成员变量在栈帧或寄存器上分配空间。
如果在一个方法中,使用到了下面class A 的一个对象。原本这个对象的两个成员变量string和int要在堆上进行分配。但是如果经过逃逸分析后,发现该对象并没有逃逸出这个方法,那么就可优化这两个成员变量为在栈上分配。
class A {
string STR = “”;
int a = 100;
}
栈上分配的效果
同样的User的对象实例,分配100000000次,启用栈上分配,只需6ms,不启用,需要3S。