Java の オートボクシング (autoboxing) は便利ですが、パフォーマンスに影響が出やすい箇所です。
簡単な比較コードに加えて、JMH (Java Microbenchmark Harness) を使って「本当にどのくらい遅いのか」を測るサンプルを紹介します。
まず:オートボクシングとは
プリミティブ型(int, double など)とラッパークラス(Integer, Double など)の間で、
自動的に変換(ボクシング/アンボクシング) が行われる仕組み。
int a = 10;
Integer b = a; // ← オートボクシング
int c = b; // ← アンボクシング
便利ですが、毎回オブジェクトを生成するため、大量ループなどでは遅くなる可能性があります。
キャッシュ範囲(-128~127)の確認コード
Java では Integer の値が -128〜127 の範囲にある場合、
同じインスタンスを再利用する(キャッシュ) 仕組みがあります。
public class IntegerCacheDemo {
public static void main(String[] args) {
Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a == b); // true (キャッシュ)
System.out.println(c == d); // false (別インスタンス)
}
}
Java🔹 結果
true
false
→ Integer.valueOf() が内部でキャッシュを使っているため。
オートボクシングによるパフォーマンス実験(単純版)
public class AutoboxingPerfTest {
public static void main(String[] args) {
long start, end;
// プリミティブ型
start = System.nanoTime();
long sum1 = 0;
for (int i = 0; i < 100_000_000; i++) {
sum1 += i;
}
end = System.nanoTime();
System.out.println("Primitive: " + (end - start) / 1_000_000 + " ms");
// オートボクシングあり
start = System.nanoTime();
Long sum2 = 0L;
for (int i = 0; i < 100_000_000; i++) {
sum2 += i; // ← ここで毎回ボクシング/アンボクシング
}
end = System.nanoTime();
System.out.println("Boxed: " + (end - start) / 1_000_000 + " ms");
}
}
Java🔹 実行結果(環境により異なる)
Primitive: 30 ms
Boxed: 800 ms
→ オートボクシングは数十倍遅いこともあります。
JMH を使った正確なベンチマーク例
JMH(Java Microbenchmark Harness)は
Java公式のマイクロベンチマークツールです。
(OpenJDK 付属、MavenやGradleでも使えます)
依存関係(Mavenの場合)
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.37</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
<scope>provided</scope>
</dependency>
JMH サンプルコード
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 3)
@Measurement(iterations = 5)
@Fork(1)
public class AutoboxingBenchmark {
private static final int N = 1000;
@Benchmark
public long primitiveSum() {
long sum = 0;
for (int i = 0; i < N; i++) {
sum += i;
}
return sum;
}
@Benchmark
public Long boxedSum() {
Long sum = 0L;
for (int i = 0; i < N; i++) {
sum += i; // ← オートボクシング発生
}
return sum;
}
}
Java実行:
mvn clean install
java -jar target/benchmarks.jar
🧾 例: 実行結果(目安)
Benchmark Mode Cnt Score Error Units
AutoboxingBenchmark.boxedSum avgt 5 2500.123 ± 30.456 ns/op
AutoboxingBenchmark.primitiveSum avgt 5 120.456 ± 5.321 ns/op
→ オートボクシングのほうが 約20倍遅い。
まとめ
| 項目 | 内容 |
|---|---|
| オートボクシング | プリミティブ ⇔ ラッパーを自動変換 |
| キャッシュ範囲 | -128 ~ 127 は同じ Integer インスタンス |
| 性能への影響 | ループや大量処理では大幅に遅くなる |
| JMH | 高精度なパフォーマンス比較が可能 |

