Skip to content

JDK 21 アップグレード時の NoSuchFieldError: JCImport コンパイルエラーの解決

問題の説明

Java 21 にアップグレードした Spring Boot プロジェクトで、以下のコンパイルエラーが発生するケースが報告されています:

bash
Fatal error compiling: java.lang.NoSuchFieldError:
Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'

このエラーは主に Lombok と JDK 21 の互換性問題が原因で発生します。JDK 21 では内部APIが変更され、古いバージョンのLombokが対応していないためです。

根本原因と解決策

主な原因: Lombok の非互換

Lombok 1.18.30 未満は JDK 21 をサポートしていません。Lombok 1.18.30 以上が必須です。

推奨解決方法: Lombok と Spring Boot のバージョンアップ

1. Lombokを1.18.30+にアップグレード
pom.xmlに明示的にバージョンを指定:

xml
<properties>
    <lombok.version>1.18.30</lombok.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

重要

Spring Bootの依存管理(BOM)でLombokバージョンが上書きされる可能性があります。親POMで定義されているLombokバージョンを確認してください。

2. Spring Boot 3.1.4+ を使用
Spring Boot 3.1.4以降はJDK 21を公式サポート:

xml
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.3</version> <!-- 最新安定版を推奨 -->
    <relativePath/>
</parent>

注意

Spring Boot 2.xを使用する場合は、明示的にLombokバージョンを指定する必要があります(BOMが古いLombokを参照するため)。

マルチモジュールプロジェクト対応

親モジュールと子モジュールで双方にJavaバージョン設定が必要:

xml
<properties>
    <java.version>21</java.version>
    <spring.boot.version>3.2.3</spring.boot.version>
</properties>
xml
<properties>
    <maven.compiler.source>21</maven.compiler.source>
    <maven.compiler.target>21</maven.compiler.target>
    <spring.boot.version>3.2.3</spring.boot.version> <!-- 親と同じバージョン -->
</properties>

追加設定が必要なケース

1. アノテーションプロセッサの設定

MapStruct等と併用する場合の設定例:

xml
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>1.18.30</version>
                    </path>
                    <!-- 他のアノテーションプロセッサ -->
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

2. Spring Boot Maven Pluginの除外設定

Lombokを実行時依存から除外:

xml
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <excludes>
            <exclude>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </exclude>
        </excludes>
    </configuration>
</plugin>

3. IntelliJでのキャッシュ問題

変更後にエラーが解消しない場合:

  1. Mavenプロジェクトの再インポート
    pom.xml右クリック → MavenReload Project
  2. IntelliJの再起動
  3. キャッシュクリーン
    FileInvalidate Caches...Invalidate and Restart

よくある落とし穴

  • 依存関係のバージョン競合: mvn dependency:treeでLombok以外の依存が古いバージョンを引き込んでいないか確認
  • モジュール間のバージョン不一致: マルチモジュールで一部モジュールのみJDK 21になっていないか確認
  • IDEキャッシュ: 設定変更後は必ずプロジェクトリロードまたはIDE再起動

バージョン互換性表

コンポーネントJDK 21 対応最小バージョン
Lombok1.18.30
Spring Boot3.1.4
MapStruct1.5.5.Final

根本解決の重要性

一時的な回避策ではなく、LombokとSpring Bootの適切なバージョン組み合わせが最も安定した解決策です。Spring Boot公式ドキュメントでも、BOMで管理されないバージョンの上書きは互換性問題を引き起こす可能性があると警告されています。

非推奨な対応

JDKをダウングレードする方法は一時的な回避策であり、新機能を使用できないというデメリットがあります。