从Java 17升级至Java 21时遭遇UnsupportedOperationException问题求助
Java 21升级后Serenity + Cucumber测试反射权限错误解决方法
我的代码基于cucumber-java8和Serenity框架开发,在Java 17环境下执行mvn test可以正常运行Cucumber用例,但升级到Java 21后,测试抛出如下运行时错误:
Caused by: java.lang.UnsupportedOperationException: Cannot define class using reflection: Unable to make protected java.lang.Package java.lang.ClassLoader.getPackage(java.lang.String) accessible: module java.base does not "opens java.lang" to unnamed module @6bc168e5 at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$Initializable$Unavailable.defineClass(ClassInjector.java:472) at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection.injectRaw(ClassInjector.java:284) at net.bytebuddy.dynamic.loading.ClassInjector$AbstractBase.inject(ClassInjector.java:118) at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default$InjectionDispatcher.load(ClassLoadingStrategy.java:241) at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default.load(ClassLoadingStrategy.java:148) at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:101) at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6166) at net.serenitybdd.rest.utils.RestSpecificationFactory.<clinit>(RestSpecificationFactory.java:60) at net.serenitybdd.rest.utils.RestDecorationHelper.decorate(RestDecorationHelper.java:20) at net.serenitybdd.rest.SerenityRest.fetchRequestSpecification(SerenityRest.java:233) at net.serenitybdd.rest.SerenityRest.given(SerenityRest.java:220)
切换回Java 17后测试恢复正常,当前项目依赖版本配置如下:
<cucumber.version>7.9.0</cucumber.version> <junit.version>4.13.2</junit.version> <junit.jupiter.version>5.9.0</junit.jupiter.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <serenity.version>4.1.6</serenity.version> <webdriver.driver>provided</webdriver.driver> <maven.surefire.version>3.5.2</maven.surefire.version> <java.version>21</java.version>
问题原因
Java 21对模块系统的访问控制进一步收紧,当前使用的Serenity 4.1.6版本依赖的ByteBuddy库未适配Java 21的模块权限规则,导致动态生成类时无法通过反射访问java.lang包下的受限方法。
解决方法
1. 优先升级Serenity到兼容Java 21的版本
Serenity后续版本已经修复了Java 21的兼容性问题,建议将serenity.version升级到4.1.10及以上(或最新稳定版),新版本会自动适配Java 21的模块要求,同时更新依赖的ByteBuddy版本。
修改pom.xml中的版本:
<serenity.version>4.1.12</serenity.version> <!-- 示例最新稳定版,可根据实际情况调整 -->
2. 临时 workaround:添加JVM模块开放参数(不推荐长期使用)
如果暂时无法升级依赖,可以在Maven Surefire插件中添加JVM参数,开放java.lang包的访问权限给未命名模块:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>${maven.surefire.version}</version> <configuration> <argLine> --add-opens java.lang/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.ClassLoader=ALL-UNNAMED </argLine> </configuration> </plugin>
执行mvn test时,插件会自动将这些参数传递给JVM,临时绕过模块权限限制。
内容的提问来源于stack exchange,提问作者Stephen Prasad
相关产品推荐
相关产品推荐

