JVM - 棧上分配 + 逃逸分析 + 標量替換
棧上分配
虛擬機器提供的一種優化技術,基本思想是,對於執行緒私有的物件,將它打散分配在棧上,而不分配在堆上。好處是物件跟著方法呼叫自行銷燬,不需要進行垃圾回收,可以提高效能。
棧上分配需要的技術基礎,逃逸分析。逃逸分析的目的是判斷物件的作用域是否會逃逸出方法體。注意,任何可以在多個執行緒之間共享的物件,一定都屬於逃逸物件。
//例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。