この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:6
ページ更新者:atom
更新日時:2026-06-11 07:10:02

タイトル: エラー一覧
SEOタイトル: Java のよくある例外・エラー一覧と対処法 — NPE / ClassNotFoundException / OOM ほか

この記事の要点
  • Java の例外は RuntimeException (非検査)Exception (検査) に分かれる
  • 最頻出は NullPointerException。null チェック・Optional・Objects.requireNonNull で予防
  • ClassNotFoundExceptionNoClassDefFoundError は別物。前者はロード時、後者は初期化中に発生
  • コレクション操作中の変更で ConcurrentModificationException が出る → Iterator.remove や CopyOnWriteArrayList を使う
  • OutOfMemoryError はメモリ不足。ヒープダンプ -XX:+HeapDumpOnOutOfMemoryError で解析

Java の例外階層

Throwable
├── Error                          (回復不能、捕捉非推奨)
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── NoClassDefFoundError
└── Exception
    ├── RuntimeException           (非検査例外: catch 不要)
    │   ├── NullPointerException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── ClassCastException
    │   ├── NumberFormatException
    │   ├── ConcurrentModificationException
    │   ├── UnsupportedOperationException
    │   └── IllegalArgumentException
    └── (検査例外: catch または throws 必須)
        ├── IOException
        ├── SQLException
        └── ClassNotFoundException

1. NullPointerException (NPE)

最頻出。null の参照型に対してメソッド・フィールドアクセスした場合に発生。

String name = null;
int len = name.length();    // ❌ NullPointerException

// 対処1: null チェック
if (name != null) {
    int len = name.length();
}

// 対処2: Optional
Optional.ofNullable(name).map(String::length).ifPresent(System.out::println);

// 対処3: 定数を左に置く (文字列比較)
if ("admin".equals(role)) { ... }  // role が null でも安全

// 対処4: Objects.requireNonNull で早期失敗
public void setName(String name) {
    this.name = Objects.requireNonNull(name, "name must not be null");
}

// Java 14+ Helpful NullPointerExceptions
// → "Cannot invoke 'String.length()' because 'name' is null" のように原因を表示

2. ClassNotFoundException / NoClassDefFoundError

ClassNotFoundExceptionNoClassDefFoundError
種類検査例外Error
発生タイミングClass.forName() / リフレクションでクラスをロード時クラスのリンク・初期化時
典型原因クラスパスに JAR が無い初期化中の static 初期化で例外発生
対処クラスパスに JAR を追加static 初期化の例外を直す / 依存 JAR を確認
Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
→ MySQL ドライバ JAR をクラスパスに追加

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
    Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
→ SLF4J の依存が pom.xml に無い、または scope=provided になっている

3. ArrayIndexOutOfBoundsException

int[] arr = {1, 2, 3};
int x = arr[5];   // ❌ ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3

// 対処: 範囲チェック
if (i >= 0 && i < arr.length) {
    int x = arr[i];
}

// 拡張 for で防ぐ
for (int v : arr) {
    System.out.println(v);
}

// 同種: StringIndexOutOfBoundsException
"abc".charAt(10);  // ❌

4. ClassCastException

Object obj = "hello";
Integer i = (Integer) obj;   // ❌ ClassCastException

// 対処1: instanceof で事前確認
if (obj instanceof Integer i2) {   // Java 16+ パターンマッチ
    System.out.println(i2 + 1);
}

// 対処2: ジェネリクスを使い raw type を避ける
List<String> list = new ArrayList<>();
list.add("a");
String s = list.get(0);   // キャスト不要で安全

5. ConcurrentModificationException

List<String> list = new ArrayList<>(List.of("a", "b", "c"));

// ❌ 拡張 for の中で remove → ConcurrentModificationException
for (String s : list) {
    if (s.equals("b")) list.remove(s);
}

// ✅ 対処1: Iterator.remove
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if (it.next().equals("b")) it.remove();
}

// ✅ 対処2: removeIf (Java 8+)
list.removeIf(s -> s.equals("b"));

// ✅ 対処3: 並行アクセスなら CopyOnWriteArrayList
List<String> safe = new CopyOnWriteArrayList<>(list);

6. StackOverflowError

// 無限再帰でスタックが溢れる
public int factorial(int n) {
    return n * factorial(n - 1);   // ❌ 終了条件無し
}

// 対処: 終了条件を入れる
public int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

// JVM 引数でスタックサイズ調整 (緊急避難)
// java -Xss2m MyApp

7. OutOfMemoryError

java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Metaspace
java.lang.OutOfMemoryError: GC overhead limit exceeded
java.lang.OutOfMemoryError: Direct buffer memory

対処:

  • ヒープサイズを増やす: java -Xmx2g -Xms512m MyApp
  • ヒープダンプを取得: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp
  • VisualVM / Eclipse MAT でメモリリーク調査
  • Metaspace の場合: -XX:MaxMetaspaceSize=256m

8. UnsupportedOperationException

// 不変リストへの変更
List<Integer> nums = List.of(1, 2, 3);   // 不変
nums.add(4);   // ❌ UnsupportedOperationException

// Arrays.asList も追加・削除不可
List<Integer> a = Arrays.asList(1, 2, 3);
a.add(4);   // ❌

// 対処: 可変リストにコピー
List<Integer> mutable = new ArrayList<>(nums);
mutable.add(4);   // ✅

9. NumberFormatException

int n = Integer.parseInt("abc");   // ❌ NumberFormatException
int m = Integer.parseInt("");      // ❌ 同様
int o = Integer.parseInt(null);    // ❌ 同様 (Java 8+) または NPE

// 対処: try-catch または事前バリデーション
try {
    int n = Integer.parseInt(s);
} catch (NumberFormatException e) {
    n = 0;   // デフォルト値
}

// Apache Commons NumberUtils なら例外を投げない
int n = NumberUtils.toInt(s, 0);

10. IOException 系

// 検査例外なので try-catch または throws 必須

// ファイル無し
try {
    String txt = Files.readString(Path.of("notfound.txt"));
} catch (NoSuchFileException e) {
    // ファイルが存在しない
} catch (IOException e) {
    // その他の I/O エラー
}

// ネットワーク
try (Socket sock = new Socket("example.com", 80)) {
    // ...
} catch (UnknownHostException e) {
    // DNS 解決失敗
} catch (ConnectException e) {
    // 接続拒否
} catch (SocketTimeoutException e) {
    // タイムアウト
} catch (IOException e) {
    // その他
}

FAQ

Q: 検査例外と非検査例外、どちらを投げるべき?
A: 呼び出し側が回復可能なら検査例外、プログラムバグなら非検査例外。現代のフレームワーク (Spring 等) は非検査例外を好む傾向。

Q: 例外を catch して何もしない (空 catch) は問題?
A: 重大なバグの温床。最低限 log.error("...", e) でログに残してください。

Q: NPE を完全に防ぐ方法は?
A: 完全には不可能ですが、Optional の活用@NonNull / @Nullable アノテーションKotlin への移行で大幅に減らせます。