Java虛擬機-逃逸分析(Escape Analysis)和棧上分配

我們都知道Java中的對象默認都是分配到堆上,在調用棧中,只保存了對象的指針。當對象不再使用後,需要依靠GC來遍歷引用樹並回收內存。如果堆中對象數量太多,回收對象還有整理內存,都會會帶來時間上的消耗,GC表示壓力很大,然後影響性能。所以,在我們日常開發中,內存,時間都是相當的寶貴,該如何優化堆棧開銷,是一個比較重要的問題。

逃逸分析(Escape Analysis)和棧上分配是對JVM進行優化的常規手段,本文主要深入瞭解一下。

一、概念

1.逃逸

當變量(或者對象)在方法中分配後,其指針有可能被返回或者被全局引用,這樣就會被其他方法或者線程所引用,這種現象稱作指針(或者引用)的逃逸(Escape)。通俗點講,如果一個對象的指針被多個方法或者線程引用時,那麼我們就稱這個對象的指針(或對象)的逃逸(Escape)。

具體而言,分爲方法逃逸和線程逃逸兩種。

方法逃逸:在一個方法體內,定義一個局部變量,而它可能被外部方法引用,比如作爲調用參數傳遞給方法,或作爲對象直接返回。或者,可以理解成對象跳出了方法。

線程逃逸:這個對象被其他線程訪問到,比如賦值給了實例變量,並被其他線程訪問到了。對象逃出了當前線程。

2.棧上分配

主要是指在Java程序的執行過程中,在方法體中聲明的變量以及創建的對象,將直接從該線程所使用的棧中分配空間。 就是把沒發生逃逸的對象,在棧上分配空間。一般而言,創建對象都是從堆中來分配的,這些對象是有可能發生逃逸的。

3.逃逸分析

是一種可以有效減少Java程序中同步負載和內存堆分配壓力的跨函數全局數據流分析算法。通過逃逸分析,Java Hotspot編譯器能夠分析出一個新的對象的引用的使用範圍從而決定是否要將這個對象分配到堆上。

在JDK 6之後支持對象的棧上分析和逃逸分析,在JDK 7中完全支持棧上分配對象。 其是否打開逃逸分析依賴於以下JVM的設置:

#強制開啓:    
-server -XX:+DoEscapeAnalysis -XX:+PrintGCDetail -Xmx10m -Xms10m
#關閉逃逸分析:    
-server -XX:-DoEscapeAnalysis -XX:+PrintGCDetail -Xmx10m -Xms10m

二、爲什麼需要逃逸分析和棧上分配?

爲了GC性能。GC主要回收的對象是堆和方法區。GC不會對棧、程序計數器這些進行回收的,因爲沒東西可以回收。

如果方法逃逸,那麼對象就會分配在堆中,這個時候,GC就要工作了。如果沒發生方法逃逸,那麼對象就分配在棧中,當方法結束後,資源就自動釋放了,GC壓根不用操心。所以方法逃逸就是爲GC來服務的。GC不運行的時候,程序的性能肯定會好點,不會佔用程序運行的時間。雖然GC清掃垃圾的速度很快,但是當一個程序足夠大的時候,對象就自然多了,垃圾也自然多了,這個時候GC就忙了。

而進行逃逸分析,就是把那些不會發生逃逸的對象直接分配在棧中,這樣不需要GC參與資源的釋放,性能自然就會有提升了。

三、 逃逸分析和棧上分配的優劣勢分析

1.優勢

同步消除:線程同步的代價是相當高的,同步的後果是降低併發性和性能。逃逸分析可以判斷出某個對象是否始終只被一個線程訪問,如果只被一個線程訪問,那麼對該對象的同步操作就可以轉化成沒有同步保護的操作,這樣就能大大提高併發程度和性能。
標量替換:逃逸分析方法如果發現對象的內存存儲結構不需要連續進行的話,就可以將對象的部分甚至全部都保存在CPU寄存器內,這樣能大大提高訪問速度。

2.劣勢

棧上分配受限於棧的空間大小,一般自我迭代類的需求以及大的對象空間需求操作,將導致棧的內存溢出;故只適用於一定範圍之內的內存範圍請求。

四、參數配置一覽

逃逸分析在JDK6U23以上都是默認開啓的,開啓後會極大地提升性能。

-XX:+DoEscapeAnalysis開啓逃逸分析(JDK 6u23以上默認開啓)
-XX:-DoEscapeAnalysis 關閉逃逸分析

#標量替換基於分析逃逸基礎之上,開啓標量替換必須開啓逃逸分析
-XX:+EliminateAllocations開啓標量替換(jdk1.8默認開啓,其它版本未測試)
-XX:-EliminateAllocations 關閉標量替換

#鎖消除基於分析逃逸基礎之上,開啓鎖消除必須開啓逃逸分析
-XX:+EliminateLocks開啓鎖消除(jdk1.8默認開啓,其它版本未測試)
-XX:-EliminateLocks 關閉鎖消除

五、總結

  1. 能在方法內創建對象,就不要再方法外創建對象。畢竟這是爲了GC好,也是爲了提高性能。
  2. 棧上分配可以提升代碼性能,降低在多線程情況下的鎖使用,但是會受限於其空間的大小。
  3. 逃逸分析的效果只能在特定場景下,滿足高頻和高數量的小容量的變量分配結構,纔是合適的。

參考資料:

  1. https://www.jianshu.com/p/3ecc626ce304
  2. https://blog.csdn.net/blueheart20/article/details/52050545
  3. https://www.cnblogs.com/fuguoliang/p/9753061.html
  4. https://www.jianshu.com/p/04fcd0ea5af7
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章