對象必定分配在堆中嗎?java
JVM經過逃逸分析,那些逃不出方法的對象會在棧上分配。優化
什麼是逃逸分析?線程
EscapeAnalysis,逃逸分析,指的是虛擬機在運行期
經過計算分析將本來在堆上分配的對象改爲在棧中分配,這樣的好處是棧上分配的對象隨着線程的結束而自動銷燬,不依賴於GC,能夠下降垃圾收集器運行的頻率。code
如何斷定爲逃逸?對象
JVM判斷新建立的對象是否逃逸的依據有兩個:內存
若是知足了以上狀況的任意一種,那這個對象JVM就會斷定爲逃逸,對以上兩種狀況舉例,樣例來源於:https://zhuanlan.zhihu.com/p/59215831get
public class EscapeTest { public static Object globalVariableObject; public Object instanceObject; public void globalVariableEscape(){ globalVariableObject = new Object(); // 靜態變量,外部線程可見,發生逃逸 } public void instanceObjectEscape(){ instanceObject = new Object(); // 賦值給堆中實例字段,外部線程可見,發生逃逸 } public Object returnObjectEscape(){ return new Object(); // 返回實例,外部線程可見,發生逃逸 } public void noEscape(){ Object noEscape = new Object(); // 僅建立線程可見,對象無逃逸 } }
Java的逃逸分析只能發生在即時編譯(JIT)期,爲何不能在靜態編譯(javac)中?同步
參考R大回答:https://www.zhihu.com/questio...虛擬機
總結來講是能夠發生在靜態編譯期的,可是Java的分離編譯和動態加載使得前期的靜態編譯的逃逸分析比較困難或收益較少,因此目前Java的逃逸分析只發在JIT的即時編譯中,由於收集到足夠的運行數據JVM能夠更好的判斷對象是否發生了逃逸。io
JVM開啓逃逸分析之後的優點?
Java8+默認是開啓的,
-XX:+DoEscapeAnalysis
棧上分配,虛擬機參數:-XX:+PrintGC -Xms5M -Xmn5M -XX:+DoEscapeAnalysis
這種優化能夠下降垃圾收集器運行的頻率,這樣每當方法出棧,對象內存隨之釋放。
public static void main(String[] args) { for(int i = 0; i < 5000000; i++) { createObject(); } } public static void createObject() { new Object(); }
同步消除
標量替換