SpringBoot使用@EnableScheduling时遇反射访问权限异常求助
解决SpringBoot启用@EnableScheduling时的InaccessibleObjectException异常
问题描述
启用@EnableScheduling后触发java.lang.reflect.InaccessibleObjectException异常,提示无法访问ScheduledThreadPoolExecutor的protected方法decorateTask(),核心原因是Java 17的模块机制限制,java.base模块未向未命名模块开放java.util.concurrent包,导致Spring Cloud Sleuth通过反射访问该方法时失败。
decorateTask()是ScheduledThreadPoolExecutor的protected方法,仅允许子类或同包类访问,但此处是框架层面的反射调用问题,并非业务代码访问权限错误。
环境版本
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.2</version> <relativePath/> <!-- lookup parent from repository --> </parent>
<java.version>17</java.version> <spring-cloud.version>2021.0.3</spring-cloud.version>
完整异常栈
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make protected java.util.concurrent.RunnableScheduledFuture java.util.concurrent.ScheduledThreadPoolExecutor.decorateTask(java.lang.Runnable,java.util.concurrent.RunnableScheduledFuture) accessible: module java.base does not "opens java.util.concurrent" to unnamed module @525b461a at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) at io.armadillo.aftfileuploads.AftFileUploadsApplication.main(AftFileUploadsApplication.java:23) Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected java.util.concurrent.RunnableScheduledFuture java.util.concurrent.ScheduledThreadPoolExecutor.decorateTask(java.lang.Runnable,java.util.concurrent.RunnableScheduledFuture) accessible: module java.base does not "opens java.util.concurrent" to unnamed module @525b461a 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.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:577) at org.springframework.cloud.sleuth.instrument.async.LazyTraceScheduledThreadPoolExecutor.makeAccessibleIfNotNull(LazyTraceScheduledThreadPoolExecutor.java:121) at org.springframework.cloud.sleuth.instrument.async.LazyTraceScheduledThreadPoolExecutor.<init>(LazyTraceScheduledThreadPoolExecutor.java:205) at org.springframework.cloud.sleuth.instrument.async.LazyTraceThreadPoolTaskScheduler.getScheduledThreadPoolExecutor(LazyTraceThreadPoolTaskScheduler.java:181) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.cloud.sleuth.instrument.async.ExecutorMethodInterceptor.invoke(ExecutorBeanPostProcessor.java:356) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) at org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler$$EnhancerBySpringCGLIB$$19449eea.getScheduledThreadPoolExecutor(<generated>) at org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration.safeGetThreadPoolExecutor(TaskExecutorMetricsAutoConfiguration.java:83) at org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration.lambda$bindTaskExecutorsToRegistry$0(TaskExecutorMetricsAutoConfiguration.java:61) at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) at org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration.bindTaskExecutorsToRegistry(TaskExecutorMetricsAutoConfiguration.java:56) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:724) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ... 17 common frames omitted
解决方案
1. 添加JVM启动参数
通过JVM参数开放模块访问权限,让java.base模块允许未命名模块反射访问java.util.concurrent包:
- IDE启动:在VM Options中添加
--add-opens java.base/java.util.concurrent=ALL-UNNAMED - Maven启动:在spring-boot-maven-plugin中配置
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <jvmArguments>--add-opens java.base/java.util.concurrent=ALL-UNNAMED</jvmArguments> </configuration> </plugin>
2. 升级依赖版本
该问题源于Spring Cloud Sleuth 2021.0.3与Java 17的兼容性缺陷,可通过升级依赖解决:
- 升级Spring Cloud到2021.0.x系列的最新版本(如2021.0.5),修复Java 17兼容问题
- 若长期维护,建议迁移到Micrometer Tracing替代Spring Cloud Sleuth(Sleuth已进入维护模式),同时升级到Spring Boot 3.x+版本
3. 禁用相关自动配置
如果不需要对应的功能,可直接禁用引发问题的自动配置类:
- 禁用Task Executor Metrics自动配置:
在启动类添加:
或在application.properties中配置:@SpringBootApplication(exclude = {TaskExecutorMetricsAutoConfiguration.class})spring.autoconfigure.exclude=org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration - 禁用Sleuth异步 instrumentation:
spring.sleuth.async.enabled=false
内容的提问来源于stack exchange,提问作者localhost
相关产品推荐
相关产品推荐

