You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@Configuration触发InaccessibleObjectException异常求助

Spring 5.3.29 + JDK17 使用@Configuration注解抛出异常的排查与解决

环境与问题现象

  • JDK版本:17.0.7
  • Spring版本:5.3.29
  • 问题:使用@Configuration注解配置类时,启动Spring上下文抛出反射访问异常;但将注解替换为@Component或@Configurable时,代码可正常运行。

代码示例

File 1: Book类

package java_config;

public class Book {
    private String name;
    private double price;

    public Book() {
        super();
    }

    public Book(String name, double price) {
        super();
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book [name=" + name + ", price=" + price + "]";
    }

}

File 2: Student类

package java_config;

public class Student {
    private String name;
    private String subject;
    private Book book;

    public Student() {
        super();
    }

    public Student(String name, String subject, Book book) {
        super();
        this.name = name;
        this.subject = subject;
        this.book = book;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", subject=" + subject + ", book=" + book + "]";
    }

}

File 3: JavaConfig配置类

package java_config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
public class JavaConfig {

    @Bean
    public Book getBook() {
        return new Book("Let Us C", 200);
    }

    @Bean
    public Student getStudent() {
        return new Student("Ashutosh", "PCM", getBook());
    }
}

File 4: 启动类JavaConfigurationDemo

package java_config;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class JavaConfigurationDemo {

    public static void main(String[] args) {
        // 以下代码行抛出异常
        ApplicationContext ctx = 
                new AnnotationConfigApplicationContext(JavaConfig.class);
        
        Student student = ctx.getBean("getStudent", Student.class);
        
        System.out.println("Student's book name : " + student.getBook().getName());
    }

}

控制台异常信息

Exception in thread "main" 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 @73f792cf
    at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:600)
    at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
    at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108)
    at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
    at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572)
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:419)
    at org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(ConfigurationClassEnhancer.java:137)
    at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:109)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:447)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:268)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:325)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:147)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:748)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:93)
    at java_config.JavaConfigurationDemo.main(JavaConfigurationDemo.java:10)
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 @73f792cf
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
    at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
    at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
    at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:552)
    ... 22 more

原因分析

  1. @Configuration的特殊性:Spring会对标注@Configuration的类生成CGLIB代理,目的是拦截@Bean方法的调用,保证Bean的单例特性(直接调用配置类中的@Bean方法时,返回的是Spring容器中的单实例,而非新创建对象)。
  2. JDK17模块系统限制:JDK17的模块访问控制机制(JPMS)默认禁止未命名模块访问java.base模块中的java.lang.ClassLoader.defineClass方法,而Spring 5.3.29依赖的CGLIB版本无法绕过这个限制,导致生成代理类时抛出反射访问异常。
  3. 其他注解正常的原因:@Component或@Configurable不会触发Spring的CGLIB代理生成逻辑,因此不会触发该反射访问限制。

解决方法

方法1:升级Spring版本到5.3.30及以上

Spring官方在5.3.30版本中修复了JDK17下CGLIB代理生成的兼容性问题,升级后无需额外配置即可正常使用@Configuration注解。

方法2:添加JVM启动参数开放模块访问权限

如果无法升级Spring版本,可在启动程序时添加以下JVM参数,允许未命名模块访问java.base中的相关包:

--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED

方法3:调整配置类写法(可选)

将配置类中直接调用@Bean方法的逻辑改为通过方法参数注入Bean,虽然这不能解决代理生成的根本问题,但能更符合Spring的规范写法:

@Configuration
public class JavaConfig {

    @Bean
    public Book getBook() {
        return new Book("Let Us C", 200);
    }

    @Bean
    public Student getStudent(Book book) { // 通过参数注入Book Bean
        return new Student("Ashutosh", "PCM", book);
    }
}

内容的提问来源于stack exchange,提问作者Kaustubh Choudhary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:10:59