JDK 21 アップグレード時の NoSuchFieldError: JCImport
コンパイルエラーの解決
問題の説明
Java 21 にアップグレードした Spring Boot プロジェクトで、以下のコンパイルエラーが発生するケースが報告されています:
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
に明示的にバージョンを指定:
<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を公式サポート:
<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バージョン設定が必要:
<properties>
<java.version>21</java.version>
<spring.boot.version>3.2.3</spring.boot.version>
</properties>
<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等と併用する場合の設定例:
<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を実行時依存から除外:
<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でのキャッシュ問題
変更後にエラーが解消しない場合:
- Mavenプロジェクトの再インポート
pom.xml
右クリック → Maven → Reload Project - IntelliJの再起動
- キャッシュクリーン
File → Invalidate Caches... → Invalidate and Restart
よくある落とし穴
- 依存関係のバージョン競合:
mvn dependency:tree
でLombok以外の依存が古いバージョンを引き込んでいないか確認 - モジュール間のバージョン不一致: マルチモジュールで一部モジュールのみJDK 21になっていないか確認
- IDEキャッシュ: 設定変更後は必ずプロジェクトリロードまたはIDE再起動
バージョン互換性表
コンポーネント | JDK 21 対応最小バージョン |
---|---|
Lombok | 1.18.30 |
Spring Boot | 3.1.4 |
MapStruct | 1.5.5.Final |
根本解決の重要性
一時的な回避策ではなく、LombokとSpring Bootの適切なバージョン組み合わせが最も安定した解決策です。Spring Boot公式ドキュメントでも、BOMで管理されないバージョンの上書きは互換性問題を引き起こす可能性があると警告されています。
非推奨な対応
JDKをダウングレードする方法は一時的な回避策であり、新機能を使用できないというデメリットがあります。