一、前言知識鋪墊
1、逃逸對象:在一個方法內創建的對象沒有被外界引用則稱該對象為未逃逸的對象。
2、JDK1.6以后的HotSpot虛擬機支持運行時的對象逃逸分析。
3、JVM中的參數配置:
1 1)-XX:+PrintFlagsInitial --查看JVM中的默認參數信息 2 3 2)--XX:+DoEscapeAnalysis --開啟對象的逃逸分析(JDK8中默認開啟) 4 5 3)--XX:-DoEscapeAnalysis --關閉對象的逃逸分析 6 7 4)-XX:+PrintGC --輸出GC的基本信息 8 9 5)-XX:+PrintGCDetails --輸出GC的詳細信息 10 11 6)-Xmx5m/-Xms5m --最大/最小堆配置
二、對象創建時的內存分配
1、對象創建時有可能分配在堆上也有可能分配在棧上。
2、方法內部創建的小對象並且沒有逃逸可能分配在棧上。
3、JDK8默認打開逃逸分析,對JVM的執行會有性能上的提高。
4、設計對象時,假如對象不會被多線程共享,多個方法共享,此時,對象的引用應該盡量使用局部變量。
三、逃逸分析的開啟與關閉對JVM執行性能的影響
首先,我們先來看一個實例。
1 public class TestObjectInstance01 { 2 public static void main(String[] args) { 3 long start = System.currentTimeMillis(); 4 for (int i = 0; i < 100000000; i++) { 5 //調用alloc()方法 6 alloc(); 7 } 8 long end = System.currentTimeMillis(); 9 System.out.println("運行時間:"+(end-start)); 10 } 11 12 private static void alloc() { 13 //創建一個只能存儲一個字節的數組對象 14 byte[] arr = new byte[1]; 15 arr[0] = 10; 16 } 17 }
我們配置了JVM的最大/最小堆參數,並開啟了逃逸分析:
-Xmx5m -Xms5m -XX:+DoEscapeAnalysis -XX:+PrintGC
運行結果:
接着我們又關閉了逃逸分析:
-Xmx5m -Xms5m -XX:-DoEscapeAnalysis -XX:+PrintGC
運行結果:
結果分析:
我們可以看到,開啟逃逸分析時,JVM的運行性能要遠高於未開啟時。因為棧上分配的對象不需要啟動GC來進行回收,當調用的方法出棧時,該對象會自動銷毀。