Spring Boot 2.7.5+Java17反射访问jdk.proxy4模块报错求助
问题
使用Spring Boot 2.7.5(搭配Spring Framework 5.3.23)与JDK 17时,运行抛出InaccessibleObjectException,提示无法访问jdk.proxy4模块的私有静态final字段。降级至JDK 11仅出现警告,JDK 8则无问题。尝试过VM参数--add-opens java.base/java.lang=ALL-UNNAMED但未解决问题,问题源于自定义外部库中的@Log注解处理器,该处理器使用Spring的ReflectionUtils操作字段时触发错误。
注解处理器代码
package br.com.digihub.util.logging.annotation; import br.com.digihub.util.logging.Logger; import br.com.digihub.util.logging.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; import javax.servlet.ServletContext; import java.lang.reflect.Field; @Component public class LogAnnotationProcessor implements BeanPostProcessor { private ServletContext context; @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessBeforeInitialization(final Object bean, String name) throws BeansException { ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() { public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { ReflectionUtils.makeAccessible(field); if (field.getAnnotation(Log.class) != null) { Logger log = LoggerFactory.getLogger(bean.getClass()); field.set(bean, log); } } }); return bean; } }
错误日志
2022-10-26 17:25:25.697 ERROR 50184 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'teste': Unsatisfied dependency expressed through field 'tenantRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tenantRepository' defined in com.example.demo.repository.TenantRepository defined in @EnableJpaRepositories declared on DemoApplication: Cannot create inner bean '(inner bean)#77e3d05' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#77e3d05': Initialization of bean failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field private static final java.lang.reflect.Method jdk.proxy4.$Proxy117.m0 accessible: module jdk.proxy4 does not "opens jdk.proxy4" to unnamed module @15c43bd9 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:659) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.5.jar:2.7.5] at com.example.demo.DemoApplication.main(DemoApplication.java:30) ~[main/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.7.5.jar:2.7.5] Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tenantRepository' defined in com.example.demo.repository.TenantRepository defined in @EnableJpaRepositories declared on DemoApplication: Cannot create inner bean '(inner bean)#77e3d05' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#77e3d05': Initialization of bean failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field private static final java.lang.reflect.Method jdk.proxy4.$Proxy117.m0 accessible: module jdk.proxy4 does not "opens jdk.proxy4" to unnamed module @15c43bd9 at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:389) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:134) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1707) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1452) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.23.jar:5.3.23] ... 25 common frames omitted Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#77e3d05': Initialization of bean failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field private static final java.lang.reflect.Method jdk.proxy4.$Proxy117.m0 accessible: module jdk.proxy4 does not "opens jdk.proxy4" to unnamed module @15c43bd9 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:374) ~[spring-beans-5.3.23.jar:5.3.23] ... 38 common frames omitted Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private static final java.lang.reflect.Method jdk.proxy4.$Proxy117.m0 accessible: module jdk.proxy4 does not "opens jdk.proxy4" to unnamed module @15c43bd9 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.Field.checkCanSetAccessible(Field.java:178) ~[na:na] at java.base/java.lang.reflect.Field.setAccessible(Field.java:172) ~[na:na] at org.springframework.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:791) ~[spring-core-5.3.23.jar:5.3.23] at br.com.digihub.util.logging.annotation.LogAnnotationProcessor$1.doWith(LogAnnotationProcessor.java:26) ~[util-4.0.0-plain.jar:na] at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:714) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:693) ~[spring-core-5.3.23.jar:5.3.23] at br.com.digihub.util.logging.annotation.LogAnnotationProcessor.postProcessBeforeInitialization(LogAnnotationProcessor.java:24) ~[util-4.0.0-plain.jar:na] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.23.jar:5.3.23] ... 40 common frames omitted
解决方案
1. 修正注解处理器逻辑(推荐)
问题根源是处理器遍历Bean的所有字段,包括JDK动态代理生成的类(如jdk.proxy4.$Proxy117)中的私有静态方法字段,这类字段在JDK17的模块系统下无法被无命名模块访问。修改处理器,仅处理带有@Log注解的字段,且先判断注解再尝试设置字段可访问:
package br.com.digihub.util.logging.annotation; import br.com.digihub.util.logging.Logger; import br.com.digihub.util.logging.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; import javax.servlet.ServletContext; import java.lang.reflect.Field; @Component public class LogAnnotationProcessor implements BeanPostProcessor { private ServletContext context; @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessBeforeInitialization(final Object bean, String name) throws BeansException { // 仅处理带有@Log注解的字段,避免触碰代理类的私有字段 ReflectionUtils.doWithFields(bean.getClass(), field -> { Log logAnnotation = field.getAnnotation(Log.class); if (logAnnotation != null) { try { ReflectionUtils.makeAccessible(field); Logger log = LoggerFactory.getLogger(bean.getClass()); field.set(bean, log); } catch (IllegalAccessException e) { // 捕获异常,不影响其他Bean初始化 e.printStackTrace(); } } }); return bean; } }
更严谨的话,可以直接跳过代理类:
@Override public Object postProcessBeforeInitialization(final Object bean, String name) throws BeansException { Class<?> beanClass = bean.getClass(); // 跳过JDK代理类 if (beanClass.getName().startsWith("jdk.proxy") || beanClass.isProxy()) { return bean; } // 原有字段处理逻辑 ReflectionUtils.doWithFields(bean.getClass(), field -> { Log logAnnotation = field.getAnnotation(Log.class); if (logAnnotation != null) { try { ReflectionUtils.makeAccessible(field); Logger log = LoggerFactory.getLogger(bean.getClass()); field.set(bean, log); } catch (IllegalAccessException e) { e.printStackTrace(); } } }); return bean; }
2. 添加正确的VM参数开放模块
之前的参数未针对`jdk.proxy
相关产品推荐
相关产品推荐

