棧上分配
虛擬機提供的一種優化技術,基本思想是,對於線程私有的對象,將它打散分配在棧上,而不分配在堆上。好處是對象跟着方法調用自行銷毀,不需要進行垃圾回收,可以提高性能。
棧上分配需要的技術基礎,逃逸分析。逃逸分析的目的是判斷對象的作用域是否會逃逸出方法體。注意,任何可以在多個線程之間共享的對象,一定都屬於逃逸對象。
//例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。