Pipeline JDK 설정
Pipeline에서
NoSuchFieldError가 발생했다면, Jenkins가 프로젝트와 다른 JDK 버전으로 빌드하고 있을 가능성이 높습니다.
문제 상황
Jenkins Pipeline 빌드 중 아래와 같은 에러가 발생했습니다.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.10.1:compile
(default-compile) on project $project_name: 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' -> [Help 1]
이 에러는 컴파일러 내부 API(
com.sun.tools.javac)의 구조가 변경되었음을 의미합니다. 프로젝트가 의존하는 라이브러리(특히 Lombok 등)가 사용 중인 JDK 버전의 내부 API 변경을 반영하지 못할 때 발생합니다.
원인 분석
Jenkins에는 JDK 11, 17, 21 등 여러 버전이 등록되어 있을 수 있습니다. Pipeline 스크립트에서 JDK 버전을 명시하지 않으면, Jenkins 에이전트의 기본 JDK(예: JDK 21)로 빌드가 실행됩니다.
| 상황 | 프로젝트 JDK | Jenkins 빌드 JDK | 결과 |
|---|---|---|---|
| 정상 | JDK 17 | JDK 17 | 빌드 성공 |
| 문제 | JDK 17 | JDK 21 (기본값) | 내부 API 불일치로 빌드 실패 |
** 핵심 원인:** 프로젝트가 JDK 17 기반인데, Jenkins가 JDK 21로 빌드를 시도하면서 Lombok 등이 의존하는 JDK 내부 API 구조가 달라져 NoSuchFieldError가 발생한 것입니다.
해결 방법
1. Jenkins에 등록된 JDK 별칭(Name) 확인
Manage Jenkins > Tools > JDK installations 에서 사용하려는 JDK의 Name 값을 확인합니다.
예시:
| Name | JAVA_HOME |
|---|---|
| OpenJDK11 | /app/jdk-11 |
| OpenJDK17 | /app/jdk-17 |
| OpenJDK21 | /app/jdk-21 |
2. Pipeline 스크립트에 tools 블록 추가
Jenkinsfile의 tools 블록에서 프로젝트에 맞는 JDK 버전을 명시합니다.
pipeline {
agent any
tools {
// Jenkins 관리 > Tools > JDK installations에서 등록한 Name 사용
jdk 'OpenJDK17'
}
stages {
stage('Verify JDK') {
steps {
sh 'java -version'
sh 'echo $JAVA_HOME'
}
}
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
}
}
tools블록에 지정한 JDK Name은 Jenkins의 JDK installations에 등록된 Name과 ** 정확히 일치 **해야 합니다. 대소문자도 구분하므로 주의하세요.
예방 방법
| 방법 | 설명 |
|---|---|
tools 블록 항상 명시 | 모든 Jenkinsfile에 JDK 버전을 명시하여 암묵적 버전 사용 방지 |
| Lombok 버전 업데이트 | Lombok을 최신 버전으로 유지하면 상위 JDK 호환성 확보 가능 |
| 빌드 JDK 검증 단계 추가 | java -version 출력 단계를 추가하여 빌드 JDK 확인 |
Lombok과 같이 JDK 내부 API에 의존하는 라이브러리를 사용하는 프로젝트는 JDK 버전 관리에 특히 주의가 필요합니다. JDK 메이저 버전을 올릴 때는 반드시 해당 라이브러리의 호환성을 확인하세요.
정리
| 항목 | 설명 |
|---|---|
| 근본 원인 | Pipeline에서 JDK 버전을 명시하지 않으면 Jenkins 에이전트 기본 JDK 사용 |
| 해결 | tools { jdk 'Name값' } 블록으로 JDK 버전 명시 |
| Name 매칭 | Jenkins Tools의 JDK installations Name과 정확히 일치 (대소문자 구분) |
| 예방 | 모든 Jenkinsfile에 JDK 버전 명시 + Lombok 최신 버전 유지 |