逃逸分析-JIT優化

什麼是逃逸呢? java

簡單來講,當變量(或者對象)在方法中分配後,其指針有可能被返回或者被全局引用,這樣就會被其餘過程或者線程所引用,多線程

static V global_v;
public void a_method(){
   V v=b_method();
   c_method();
}
public V b_method(){
   V v=new V();
   return v;
}
public void c_method(){
   global_v=new V();
}

其中b_method方法內部生成的V對象的引用被返回給a_method方法內的變量v,c_method方法內生成的V對象被賦給了全局變量global_v。這兩種場景都發生了指針(引用)逃逸。 spa

 首先,咱們知道通常狀況下,對象是在堆中分配的,而堆是共享的,在堆上分配鎖的開銷是很是大的,再加上一些小對象碎片地分配在內存中也會致使頻繁的minorGC,所以java針對一些朝生夕死像碎片同樣分佈的小對象提供了兩種(我知道的暫時就兩種,不知道有沒有其餘的)新的在棧上分配的方案,他們分別是:TLAB和逃逸分析。TLAB是在棧上爲每一個線程在獨立建一個區來存放對象,今天就不講它先了。線程

逃逸分析: -XX:-DoEscapeAnalysis : 表示關閉逃逸分析 從jdk 1.7開始已經默認開始逃逸分析,如需關閉,須要指定-XX:-DoEscapeAnalysis翻譯

 在咱們開啓逃逸分析後, 在JIT(即時編譯:將熱點代碼翻譯成機器代碼)階段,會肯定對象是在棧上分配(當對象沒有發生逃逸)仍是在堆上分配(對象逃逸)。指針

不過,目前java的逃逸分析技術還不成熟,咱們開啓逃逸分析以後,判斷一個對象是否逃逸耗時長,若是分析完發現沒有幾個不逃逸的對象,那時間就白白浪費了。code

順便附上Java對象分配的過程:對象

1.編譯器經過逃逸分析,肯定對象是在棧上分配仍是在堆上分配。若是是在堆上分配,則進入選項2內存

2.若是tlab_top + size <= tlab_end,則在在TLAB上直接分配對象並增長tlab_top 的值,若是現有的TLAB不足以存放當前對象則3編譯器

3.從新申請一個TLAB,並再次嘗試存放當前對象。若是放不下,則4.

4.在Eden區加鎖(這個區是多線程共享的),若是eden_top + size <= eden_end則將對象存放在Eden區,增長eden_top 的值,若是Eden區不足以存放,則5.

5.執行一次Young GC(minor collection)。

6.通過Young GC以後,若是Eden區任然不足以存放當前對象,則直接分配到老年代。

對象不在堆上分配主要的緣由仍是堆是共享的,在堆上分配有鎖的開銷。不管是TLAB仍是棧都是線程私有的,私有即避免了競爭(固然也可能產生額外的問題例如可見性問題),這是典型的用空間換效率的作法。

相關文章
相關標籤/搜索