解决java.lang.ClassFormatError:模块java.base未开放java.lang至未命名模块
Spring Boot 3 + Java 17 模块系统下CGLib访问权限异常解决思路
异常信息
org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @1ed4004b at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:547) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:371) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52) ~[spring-core-6.1.3.jar:6.1.3] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na] at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:57) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:130) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:317) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:562) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:407) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(ConfigurationClassEnhancer.java:138) ~[spring-context-6.1.3.jar:6.1.3] at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:109) ~[spring-context-6.1.3.jar:6.1.3] at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:533) ~[spring-context-6.1.3.jar:6.1.3] at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:310) ~[spring-context-6.1.3.jar:6.1.3] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:363) ~[spring-context-6.1.3.jar:6.1.3] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:153) ~[spring-context-6.1.3.jar:6.1.3] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:788) ~[spring-context-6.1.3.jar:6.1.3] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:606) ~[spring-context-6.1.3.jar:6.1.3] at spring.boot@3.2.2/org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.2.jar:na] at spring.boot@3.2.2/org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.2.jar:na] at spring.boot@3.2.2/org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.2.jar:na] at spring.boot@3.2.2/org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.2.jar:na] at spring.boot@3.2.2/org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.2.jar:na] at spring.boot@3.2.2/org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.2.jar:na] Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @1ed4004b at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) ~[na:na] at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) ~[na:na] at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199) ~[na:na] at java.base/java.lang.reflect.Method.setAccessible(Method.java:193) ~[na:na] at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:505) ~[spring-core-6.1.3.jar:6.1.3] ... 26 common frames omitted
问题背景
运行Spring Boot 3.2.2 + Java 17项目时抛出上述异常,删除module-info.java后异常消失,但调整该文件的依赖声明无法解决问题。
当前module-info.java内容
module a { requires java.sql; requires spring.boot.autoconfigure; requires spring.boot; requires io.swagger.v3.oas.annotations; requires spring.web; requires org.slf4j; requires org.apache.commons.lang3; requires jakarta.validation; //exports... opens a; }
当前pom.xml内容
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>a</artifactId> <version>0.0.1-SNAPSHOT</version> <name>a</name> <properties> <java.version>17</java.version> <springdoc.version>2.3.0</springdoc.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>${springdoc.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util-ajax</artifactId> <version>9.4.46.v20220331</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
解决思路
1. 添加JVM反射权限参数
CGLib在模块模式下需要访问java.base模块的内部API,添加以下JVM启动参数:
--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
该参数允许未命名模块(如Spring部分依赖)访问java.base的指定包,解决反射权限问题。
2. 补全模块声明的依赖
当前module-info.java缺少Spring核心模块的声明,补充后让模块系统正确解析依赖:
requires spring.context; requires spring.core;
3. 排查并解决CGLib依赖冲突
通过Maven依赖树检查是否存在旧版CGLib:
mvn dependency:tree | grep cglib
若发现冲突,在spring-boot-starter-web中排除旧版,确保使用Spring自带的适配JPMS的版本:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>cglib</groupId> <artifactId>cglib</artifactId> </exclusion> </exclusions> </dependency>
4. 升级不兼容的第三方依赖
jetty-util-ajax 9.4.x未适配JPMS,升级到支持模块的版本:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util-ajax</artifactId> <version>11.0.15</version> </dependency>
5. 配置Spring Boot Maven插件的模块支持
显式指定模块名称和主类,避免打包时的模块识别问题:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>a.YourApplicationMainClass</mainClass> <moduleName>a</moduleName> </configuration> </plugin>
替换a.YourApplicationMainClass为你的主类全限定名。
内容的提问来源于stack exchange,提问作者Vincent Gates
相关产品推荐
相关产品推荐

