Analysis and Solution for Compilation Error After JDK 21 Upgrade: Investigating Lombok Compatibility Issues

Dec 03, 2025 · Programming · 9 views · 7.8

Keywords: JDK 21 | Lombok | Compilation Error | Spring Boot | Compatibility

Abstract: This paper provides an in-depth analysis of the compilation error "NoSuchFieldError: JCImport does not have member field JCTree qualid" that occurs after upgrading Spring Boot projects to JDK 21. Through a core case study, it identifies the root cause as a compatibility conflict between the Lombok library and JDK 21. The article systematically explains the necessity of Lombok 1.18.30 as the minimum compatible version and explores the dependency relationship with Spring Boot 3.1.4. Furthermore, it offers detailed solutions, including dependency management configuration and BOM override strategies, and demonstrates their implementation in practical projects through code examples. Finally, the paper summarizes best practices for version compatibility management, providing comprehensive technical guidance for developers.

Problem Background and Error Analysis

After upgrading the Java development environment to JDK 21, many Spring Boot project developers have reported a specific compilation error: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'. This error typically occurs during the compilation process, indicating that internal structures of the Java compiler have changed, causing certain dependent libraries to fail in accessing expected fields.

From a technical perspective, NoSuchFieldError is a runtime error, but its appearance at compile time suggests a mismatch between the library version in the compile-time classpath and the expected API structure at runtime. Specifically, this error points to the com.sun.tools.javac.tree.JCTree$JCImport class lacking the qualid field, directly reflecting changes in JDK internal APIs.

Root Cause: Compatibility Issues Between Lombok and JDK 21

Through thorough investigation, the root cause of this issue is identified as a compatibility conflict between the Lombok library and JDK 21. Lombok, as a widely used Java library, modifies the abstract syntax tree (AST) at compile time via annotation processors to generate code. It relies on internal APIs of the Java compiler, particularly classes in the com.sun.tools.javac package.

In JDK 21, Oracle has refactored the internal APIs of the Java compiler, including structural changes to the JCTree$JCImport class. Specifically, the qualid field may have been renamed, removed, or replaced with alternative implementations. Since earlier versions of Lombok (e.g., 1.18.26) hardcoded access paths to these internal APIs, when JDK 21 altered these APIs, Lombok could not adapt to the new structure, triggering the NoSuchFieldError.

Such compatibility issues are not uncommon in the Java ecosystem, especially when libraries deeply depend on JDK internal APIs. Internal APIs are generally not considered public contracts and may undergo incompatible changes between JDK versions. Lombok, as an actively maintained project, requires continuous updates to adapt to these changes.

Solution: Version Upgrade and Dependency Management

To resolve this compilation error, the core solution is to upgrade Lombok to a version compatible with JDK 21. According to official documentation and community feedback, Lombok 1.18.30 is the first version fully supporting JDK 21. Below are detailed steps on how to implement this upgrade in a project.

Maven Project Configuration

In Maven projects, compatibility can be ensured by directly specifying the Lombok version. Add or update the Lombok dependency in the dependencies section of pom.xml:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

If the project uses Spring Boot, note that Spring Boot's Bill of Materials (BOM) may define an older Lombok version. Spring Boot 3.1.4 is the first release to default Lombok to version 1.18.30, so upgrading Spring Boot to 3.1.4 or later can automatically resolve dependency conflicts.

Gradle Project Configuration

For Gradle projects, explicitly set the Lombok version in build.gradle or build.gradle.kts:

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.30'
    annotationProcessor 'org.projectlombok:lombok:1.18.30'
}

If using Spring Boot's Gradle plugin, it may be necessary to override the default dependency version. This can be achieved by configuring ext['lombok.version'] = '1.18.30' or specifying the version in a dependency management block.

BOM Override Strategy

When the Spring Boot BOM defines an incompatible Lombok version, developers can manually override it. In Maven, prioritize the Lombok version in the dependency management section of pom.xml:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>
    </dependencies>
</dependencyManagement>

This approach ensures the project uses the specified Lombok version, independent of the Spring Boot BOM constraints. However, overriding the BOM may introduce other dependency conflicts, so comprehensive testing of the upgraded project is recommended.

In-Depth Technical Details and Code Examples

To better understand the compatibility issue between Lombok and JDK 21, we can illustrate it with a simple code example. Suppose there is a Spring Boot entity class using Lombok:

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class User {
    private String name;
    private int age;
}

When compiling with Lombok 1.18.26 under JDK 21, Lombok's annotation processor attempts to access the qualid field of JCTree$JCImport to resolve import statements. Since this field no longer exists in JDK 21, the processor throws a NoSuchFieldError. After upgrading to Lombok 1.18.30, the processor uses updated APIs to access the AST, thus avoiding the error.

From an implementation perspective, Lombok 1.18.30 may have modified its internal code to adapt to JDK 21's API changes. For example, it might replace hardcoded field access with reflection or new API methods. Here is a simplified example simulating Lombok's internal processing:

// Pseudocode: Old Lombok handling of import statements (incompatible with JDK 21)
JCTree.JCImport importNode = ...;
JCTree qualid = importNode.qualid; // In JDK 21, this field may be renamed or removed

// Pseudocode: New Lombok handling of import statements (compatible with JDK 21)
JCTree.JCImport importNode = ...;
JCTree qualid = getQualid(importNode); // Obtain qualid via new method, adapting to API changes

This change highlights the risks of depending on internal APIs and demonstrates how library maintainers update code to maintain compatibility.

Best Practices and Preventive Measures

To prevent similar issues in the future, developers can adopt the following best practices:

Additionally, for enterprise-level projects, establishing automated compatibility testing processes is recommended to ensure that each JDK or library upgrade does not break existing functionality.

Conclusion

The compilation error "NoSuchFieldError: JCImport does not have member field JCTree qualid" after upgrading to JDK 21 stems from a compatibility break between the Lombok library and JDK internal APIs. By upgrading Lombok to version 1.18.30 or higher and adjusting Spring Boot to 3.1.4 or above, developers can effectively resolve this issue. The solutions and code examples provided in this paper offer practical guidance for real-world project upgrades, while the emphasized best practices help prevent future compatibility challenges. In the rapidly evolving Java ecosystem, maintaining synchronized dependency versions and monitoring API changes is crucial.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.