javaの脱出分析を深く理解する。


逃亡分析

public static StringBuffer craeteStringBuffer(String s1, String s2) {
  StringBuffer sb = new StringBuffer();
  sb.append(s1);
  sb.append(s2);
  return sb;
}

public static String createStringBuffer(String s1, String s2) {
  StringBuffer sb = new StringBuffer();
  sb.append(s1);
  sb.append(s2);
  return sb.toString();
}
第一段コードのsbは逃げましたが、第二段コードのsbは逃げませんでした。
Javaコードの実行時、JVMパラメータにより、エスケープ解析を開始するかどうかを指定できます。,-XX:+DoEscapeAnalysis :エスケープを閉じるという分析は、jdk 1.7からすでにデフォルトでエスケープ分析を開始しています。クローズする必要があるなら、指定-XX:-DoEscape Analysisが必要です。
作用
逃避分析を使って、コンパイラはコードを次のように最適化できます。
ロック解除
一つのオブジェクトが一つのスレッドからしかアクセスできないと発見された場合、このオブジェクトの動作は同期を考慮しなくてもよい。
ロック解除前

public void f() {
  Object o = new Object();
  synchronized(o) {
    System.out.println(o);
  }
}
ロック解除後

public void f() {
  Object o = new Object();
  System.out.println(o);
}
スカラー置換
オブジェクトまたはスカラを分離して置換します。あるオブジェクトは、連続したメモリ構造として存在する必要がなくてもアクセスできる場合があり、対象の部分(または全部)はメモリではなく、CPUレジスタに記憶されてもよい。
スカラー置換前

public static void main(String[] args) {
  alloc();
}

private static void alloc() {
  Point point = new Point(1,2);
  System.out.println("point.x="+point.x+"; point.y="+point.y);
}
class Point{
  private int x;
  private int y;
}
スカラー置換後

private static void alloc() {
  int x = 1;
  int y = 2;
  System.out.println("point.x="+x+"; point.y="+y);
}
スタック上の割り当て
Java仮想マシンでは、オブジェクトはJavaスタックにメモリを割り当てることが一般的な常識です。しかし、ある特殊な事情があって、もし逃亡分析を経て、一つの対象が逃げ出していないと発見されたら、スタック上の割り当てに最適化されるかもしれません。これでメモリを積み上げる必要がなくなり、ゴミの回収も不要になります。

public static void main(String[] args) {
  long a1 = System.currentTimeMillis();
  for (int i = 0; i < 1000000; i++) {
    alloc();
  }
  //       
  long a2 = System.currentTimeMillis();
  System.out.println("cost " + (a2 - a1) + " ms");
  //               ,  sleep
  try {
    Thread.sleep(100000);
  } catch (InterruptedException e1) {
    e1.printStackTrace();
  }
}

private static void alloc() {
  User user = new User();
}

static class User {

}
Userオブジェクトはalloc法で定義されているが、方法の外部では彼を引用していない。つまり、この対象はallocの外に逃げないということです。JITの脱出分析を経て、メモリの割り当てを最適化することができます。
脱出分析を開けていない

Xmx4G -Xms4G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
結果

➜ ~ jps
2809 StackAllocTest
2810 Jps
➜ ~ jmap -histo 2809

 num   #instances     #bytes class name
----------------------------------------------
  1:      524    87282184 [I
  2:    1000000    16000000 StackAllocTest$User
  3:     6806    2093136 [B
  4:     8006    1320872 [C
  5:     4188     100512 java.lang.String
  6:      581     66304 java.lang.Class
中国共産党は100万元のStocAllocTest$Userの実例を作成しました。
脱出分析を開く

-Xmx4G -Xms4G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError 
結果

➜ ~ jps
709
2858 Launcher
2859 StackAllocTest
2860 Jps
➜ ~ jmap -histo 2859

 num   #instances     #bytes class name
----------------------------------------------
  1:      524   101944280 [I
  2:     6806    2093136 [B
  3:     83619    1337904 StackAllocTest$User
  4:     8006    1320872 [C
  5:     4188     100512 java.lang.String
  6:      581     66304 java.lang.Class
エスケープ分析を開始した後(-XX:+DoEscape Analysis)、ヒープメモリの中には8万余りの-XX:-DoEscapeAnalysisオブジェクトしかありません。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。