라떼군 이야기
JDK 21+ Mockito "self-attaching" 경고 및 Dynamic Agent Loading 문제 해결 방법
Problem
Spring Boot 3.4.0 및 OpenJDK 21 환경에서 테스트를 실행할 때, 콘솔에 “Mockito is currently self-attaching to enable the inline-mock-maker"라는 경고 메시지가 출력되는 현상입니다. 이와 함께 “Dynamic loading of agents will be disallowed by default in a future release"라는 경고도 동반됩니다. 이는 현재는 경고 수준이지만, 향후 JDK 버전에서는 Mockito의 인라인 모킹 기능이 작동하지 않을 수 있음을 의미하므로 해결이 필요합니다.
Background
이 문제는 JDK 21부터 강화된 JEP 451: Prepare to Disallow the Dynamic Loading of Agents 정책과 관련이 있습니다. Mockito는 final 클래스나 메서드를 모킹하기 위해 mockito-inline 기능을 사용하며, 이는 내부적으로 Byte Buddy 에이전트를 실행 중인 JVM에 동적으로 부착(Self-attach)하는 방식으로 작동합니다.
하지만 최신 JDK는 보안상의 이유로 실행 중인 JVM에 에이전트를 동적으로 로드하는 것을 기본적으로 제한하려 합니다. 따라서 JVM이 시작될 때 -javaagent 옵션을 통해 명시적으로 에이전트를 로드하도록 설정해야 경고 없이 안정적으로 동작합니다.
Solution
이 문제를 해결하기 위해서는 빌드 도구(Maven 또는 Gradle)의 테스트 실행 설정에 -javaagent 옵션을 추가하여 Mockito Core jar 파일을 명시적으로 지정해야 합니다. 또한, 클래스 데이터 공유(CDS) 관련 경고를 방지하기 위해 -Xshare:off 옵션을 함께 사용하는 것이 좋습니다.
1. Maven 프로젝트 설정
pom.xml 파일의 maven-surefire-plugin 설정을 다음과 같이 수정합니다. 로컬 저장소 경로와 Mockito 버전을 동적으로 참조하여 jar 파일 경로를 지정합니다.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
<!-- Mockito 에이전트 명시적 로드 -->
-javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
<!-- CDS 경고 방지 -->
-Xshare:off
</argLine>
</configuration>
</plugin>
</plugins>
</build>
참고: ${mockito.version} 속성이 프로젝트에 정의되어 있어야 합니다. 만약 Spring Boot의 의존성 관리를 따른다면 버전을 직접 명시하거나 해당 속성을 확인하세요.
2. Gradle 프로젝트 설정
Gradle을 사용하는 경우 build.gradle 파일의 test 태스크에 jvmArgs를 추가합니다. 런타임 클래스패스에서 Mockito Core jar를 찾아 경로를 설정합니다.
test {
jvmArgs(
// 런타임 클래스패스에서 mockito-core jar 파일을 찾아 에이전트로 등록
"-javaagent:${configurations.testRuntimeClasspath.find { it.name.contains('mockito-core') }}",
// CDS 경고 방지
"-Xshare:off"
)
}
이 설정을 적용하면 커맨드 라인 빌드뿐만 아니라 IntelliJ IDEA와 같은 IDE에서 테스트를 실행할 때도 경고가 사라집니다.
Deep Dive
-Xshare:off 옵션이 필요한 이유
로그에 OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes...라는 경고가 함께 나타날 수 있습니다. 이는 Java의 Class Data Sharing (CDS) 기능이 에이전트에 의해 수정된 클래스와 충돌하기 때문입니다. -Xshare:off를 추가하면 CDS 기능을 비활성화하여 이 경고를 제거할 수 있습니다.
IDE와 빌드 도구의 차이
어떤 해결책은 Maven/Gradle 빌드 시에는 동작하지만 IDE(IntelliJ 등)에서 바로 테스트를 실행할 때는 적용되지 않을 수 있습니다. 위에서 제시한 maven-surefire-plugin의 argLine 설정이나 Gradle의 jvmArgs 설정은 빌드 도구와 IDE 모두에서 해당 설정을 인식하여 테스트 프로세스를 띄우므로 가장 호환성이 좋은 방법입니다.
Conclusion
JDK 21 이상에서 Mockito를 사용할 때 발생하는 에이전트 로딩 경고는 향후 JVM의 보안 정책 변화에 대비하기 위한 중요한 신호입니다. maven-surefire-plugin이나 Gradle test 태스크에 -javaagent 설정을 추가함으로써 이 문제를 해결하고, 미래의 JDK 버전에서도 테스트가 깨지지 않도록 미리 대비할 수 있습니다.