Java仮想マシンにおいて、オブジェクトは通常ヒープ領域に割り当てられますが、逃逸解析(Escape Analysis)技術の発展により、必ずしもヒープが唯一の選択肢ではなくなっています。
逃逸解析の基本概念
- 逃逸解析は、オブジェクトのスコープを分析し、メソッド外に「逃げる」かどうかを判断する技術
- 逃逸しないオブジェクトはスタック上に割り当て可能
- HotSpot JVMではJDK 6u23以降デフォルトで有効
逃逸解析の判断基準
// 逃逸しない例
public void localMethod() {
LocalObject obj = new LocalObject();
obj.use();
obj = null;
}
// 逃逸する例
public Object escapingMethod() {
EscapingObject obj = new EscapingObject();
return obj; // メソッド外に参照が渡る
}
逃逸解析による最適化技術
1. スタック割り当て
// ベンチマークコード例
public class StackAllocationBenchmark {
static class DataHolder {
int value;
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
createAndUse();
}
System.out.println("Time: " + (System.currentTimeMillis() - start) + "ms");
}
private static void createAndUse() {
DataHolder holder = new DataHolder(); // 逃逸しない場合スタック割り当て
holder.value = 42;
}
}
2. 同期省略(ロック除去)
// 同期が除去可能な例
public void lockEliminationExample() {
Object lock = new Object();
synchronized(lock) { // このロックは除去可能
System.out.println("Lock eliminated");
}
}
3. スカラー置換
// スカラー置換前
public void beforeScalarReplacement() {
Point p = new Point(10, 20);
System.out.println(p.x + p.y);
}
// スカラー置換後(JVMが自動変換)
public void afterScalarReplacement() {
int x = 10, y = 20;
System.out.println(x + y);
}
パフォーマンスチューニング
- -XX:+DoEscapeAnalysis: 逃逸解析を有効化(デフォルトでON)
- -XX:+PrintEscapeAnalysis: 解析結果を出力
- -XX:+EliminateAllocations: スカラー置換を有効化
逃逸解析は完全な技術ではなく、解析コストが利益を上回る場合もあるため、常に最適な結果が得られるとは限りません。しかし、現代のJVMにおいて重要な最適化技術の一つです。