Java | 「オートボクシングでのパフォーマンス」や「キャッシュ範囲の仕組み(-128〜127)」をコードで実験

Java Java
スポンサーリンク

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高精度なパフォーマンス比較が可能
Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました