瞭解逃逸分析

堆是分配對象存儲的唯一選擇嗎?

,在《深入理解Java虛擬機》中關於Java堆內存有這樣一段描述: .
隨着JIT編譯期的發展與逃逸分析技術逐漸成熟,棧上分配、標量替換優化技術將會導致一些微妙的變化,所有的對象都分配到堆上也漸漸變得不那麼“絕對”了

在Java虛擬機中,對象是在Java堆中分配內存的,這是一個普遍的常識。但是,有一種特殊情況,那就是**如果經過逃逸分析(Escape Analysis)後發現,一個對象並沒有逃逸出方法的話,那麼就可能被優化成棧上分配。**這樣就無需在堆上分配內存,也無須進行垃圾回收了。這也是最常見的堆外存儲技術。

此外,前面提到的基於openJDK深度定製的TaoBaoVM,其中創新的GCIH (GC invisible heap)技術實現off-heap,將生命週期較長的Java對象從heap中移至heap外,並且Gc不能管理GCIH內部的Java對象,以此達到降低GC的回收頻率和提升GC的回收效率的目的。

逃逸分析概述

  • 如何將堆上的對象分配到棧,需要使用逃逸分析手段。
  • 這是一種可以有效減少Java程序中同步負載和內存堆分配壓力的跨函數全局數據流分析算法。
  • 通過逃逸分析,Java Hotspot編譯器能夠分析出一個新的對象的引用的使用範圍從而決定是否要將這個對象分配到堆上。
  • 逃逸分析的基本行爲就是分析對象動態作用域:①:當一個對象在方法中被定義後,對象只在方法內部使用,則認爲沒有發生逃逸,將堆上的對象分配到棧上,隋芳芳執行結束,棧空間就被移除。②:當一個對象在方法中被定義後,它被外部方法所引用,則認爲發生逃逸。例如作爲調用參數傳遞到其他地方中。

如何快速判斷對象是否發生逃逸,就看new的對象是否有可能會在方法外被使用。
結論:開發中能使用局部變量的,就不要使用在方法外定義。

參數設置:
在JDK 6u23版本之後,Hotspot中默認就已經開啓了逃逸分析。如果使用的是較早的版本,開發人員則可以通過:
➢選項“-XX: +DlpEscapeAnalysis"顯式開啓逃逸分析
➢通過選項“-XX: +PrintEscapeAnalysis"查看逃逸分析的篩選結果。

使用逃逸分析,編譯器可以對代碼做如下優化

  1. 棧上分配。將堆分配轉化爲棧分配。如果-一個對象在子程序中被分配,要使指向該對象的指針永遠不會逃逸,對象可能是棧分配的候選,而不是堆分配。
  2. 同步省略,如果一個對象被發現只能從一個線程被訪問到,那麼對於這個對象的操作可以不考慮同步。
  3. 分離對象或標量替換。有的對象可能不需要作爲–個連續的內存結構存在也可以被訪問到,那麼對象的部分(或全部)可以不存儲在內存,而是存儲在CPU寄存器中。

棧上分配

JIT編譯器在編譯期間根據逃逸分析的結果,發現如果-一個對象並沒有逃逸出方法的話,就可能被優化成棧上分配。分配完成後,繼續在調用棧內執行,最後線程結束,棧空間被回收,局部變量對象也被回收。這樣就無須進行垃圾回收了。

同步省略

線程同步的代價是相當高的,同步的後果是降低併發性和性能。

在動態編譯同步塊的時候,JIT編譯器可以藉助逃逸分析來判斷同步塊所使用的鎖對象是否只能夠被一個線程訪問而沒有被髮布到其他線程。如果沒有,那麼JIT編譯器在編譯這個同步塊的時候就會取消對這部分代碼的同步。這樣就能大大提高併發性和性能。這個取消同步的過程就叫同步省略,也叫鎖消除。.

分離對象或標量替換

標量(Scalar) 是指一個無法再分解成更小的數據的數據。Java中的原始數據類型就是標量。

相對的,那些還可以分解的數據叫做聚合量(Aggregate),Java中的對象就是聚合量,因爲他可以分解成其他聚合量和標量。

在JIT階段,如果經過逃逸分析,發現一個對象不會被外界訪問的話,那麼經過JIT優化, 就會把這個對象拆解成若干個其中包含的若干個成員變量來代替。這個過程就是標量替換。
在這裏插入圖片描述
可以看到,Point這個聚合量經過逃逸分析後,發現他並沒有逃逸,就被替換成兩個聚合量了。那麼標量替換有什麼好處呢?就是可以大大減少堆內存的佔用。因爲一旦不需要創建對象了,那麼就不再需要分配堆內存了。標量替換爲棧上分配提供了很好的基礎。

-XX:EliminateAllocations 開啓標量替換

補充

在這裏插入圖片描述
關於逃逸分析的論文在1999年就已經發表了,但直到JDK 1.6纔有實現,而且這項技術到如今也並不是十分成熟的。
其根本原因就是無法保證逃逸分析的性能消耗一.定能高於他的消耗。雖然經過逃逸分析可以做標量替換、棧上分配、和鎖消除。但是逃逸分析自身也是需要進行一系列複雜的分析的,這其實也是一個相對耗時的過程。
一個極端的例子,就是經過逃逸分析之後,發現沒有一個對象是不逃逸的。那這個逃逸分析的過程就白白浪費掉了。雖然這項技術並不十分成熟,但是它也是即時編譯器優化技術中一個十分重要的手段。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章