SpringBoot项目启动报错java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
问题
今天启动业余学习项目里的某服务A
发现启动失败,报错信息如下:
[ ERROR] [2025-01-05 15:41:26,083] [main] com.cdfive.springboot.startup.ApplicationStartupExceptionReporter [30] - error=>
java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:724)
at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:531)
at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:355)
at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:286)
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)
at java.lang.reflect.Executable.declaredAnnotations(Executable.java:599)
at java.lang.reflect.Executable.declaredAnnotations(Executable.java:597)
at java.lang.reflect.Executable.getDeclaredAnnotations(Executable.java:588)
at java.lang.reflect.Method.getDeclaredAnnotations(Method.java:630)
at org.springframework.core.annotation.AnnotationsScanner.getDeclaredAnnotations(AnnotationsScanner.java:454)
at org.springframework.core.annotation.AnnotationsScanner.isKnownEmpty(AnnotationsScanner.java:492)
at org.springframework.core.annotation.TypeMappedAnnotations.from(TypeMappedAnnotations.java:251)
at org.springframework.core.annotation.MergedAnnotations.from(MergedAnnotations.java:351)
at org.springframework.core.annotation.MergedAnnotations.from(MergedAnnotations.java:330)
at org.springframework.core.annotation.AnnotatedElementUtils.findAnnotations(AnnotatedElementUtils.java:764)
at org.springframework.core.annotation.AnnotatedElementUtils.hasAnnotation(AnnotatedElementUtils.java:531)
at org.springframework.context.annotation.BeanAnnotationHelper.isBeanAnnotated(BeanAnnotationHelper.java:41)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.isMatch(ConfigurationClassEnhancer.java:407)
at org.springframework.context.annotation.ConfigurationClassEnhancer$ConditionalCallbackFilter.accept(ConfigurationClassEnhancer.java:192)
at org.springframework.cglib.proxy.Enhancer.emitMethods(Enhancer.java:1217)
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:726)
at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy.generate(ClassLoaderAwareGeneratorStrategy.java:57)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:358)
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.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
at java.util.concurrent.FutureTask.run(FutureTask.java)
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:433)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:258)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:291)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:131)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:402)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1247)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1236)
at com.cdfive.web.WebApplication.main(WebApplication.java:16)
第一次看到这个报错:java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
异常堆栈信息里没有项目模块里相关的东西,初步看不出来哪里的问题。
分析&解决
考虑上周在本机尝试安装新版本IDEA,后面又还原安装了老版本,尝试刷新整个项目Maven依赖,然后mvn clean package
重新启动该模块,发现还是启动失败;
尝试启动项目里另一个模块服务B
,启动成功。
咦?这什么情况。。
查看Git Log想想自己怎么改了什么,看到最近对对cdfive-sentinel
、cdfive-demo-mybatis
模块有修改和优化,
cdfive-sentinel
模块里增加了feign
的集成扩展,通过feign
的Capability
和InvocationHandlerFactory
和sentinel
的API进行集成,
cdfive-demo-mybatis模块
里引入knife4j-spring-ui
依赖,修复了影响其使用的问题。
其中,cdfive-demo-mybatis
是个独立的demo模块,服务A
和服务B
依赖它,而都有对cdfive-sentinel
模块的依赖。
为什么服务A
启动失败,服务B
启动成功呢?
注意到服务A
没有feign
的依赖,而服务B
有,在cdfive-sentinel
模块里对feign
的依赖<scope>
为provided
。
通过搜索找到一些博客分享,尝试在java.lang.ArrayStoreException
类的构造函数打断点:
public ArrayStoreException() {
super();
}
public ArrayStoreException(String s) {
super(s);
}
在断点的方法调用栈里,看到上一级AnnotationParser#parseClassArray(...)
里,找到了有个变量的类型是com.cdfive.sentinel.config.SentinelAutoConfiguration
,
是扩展sentinel
的自动配置类,上周正好修改过。
打开SentinelAutoConfiguration
类,查看新添加的代码:
@ConditionalOnClass(Feign.Builder.class)
@Bean
public SentinelBeanPostProcessor sentinelBeanPostProcessor() {
SentinelBeanPostProcessor sentinelBeanPostProcessor = new SentinelBeanPostProcessor();
return sentinelBeanPostProcessor;
}
新添加1个SentinelBeanPostProcessor
的Bean,想通过@ConditionalOnClass
注解实现当class包里有Feign.Builder
时创建该Bean,
而服务A
里没有feign
的依赖包。
根据@ConditionalOnClass
注解字面理解,它是判断class是否存在来决定是否创建Bean,
这里将注解用在方法上,遇到了问题。
查看@ConditionOnClass
注解的注释:
**
* {@link Conditional @Conditional} that only matches when the specified classes are on
* the classpath.
* <p>
* A {@link #value()} can be safely specified on {@code @Configuration} classes as the
* annotation metadata is parsed by using ASM before the class is loaded. Extra care is
* required when placed on {@code @Bean} methods, consider isolating the condition in a
* separate {@code Configuration} class, in particular if the return type of the method
* matches the {@link #value target of the condition}.
*
* @author Phillip Webb
* @since 1.0.0
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
...
}
根据查询的资料:
`@ConditionalOnClass`如果添加在类的方法里时要格外小心,考虑将条件隔离在单独的Configuration类中,
建议`@ConditionalOnClass`在类级别使用,如果在方法上使用,考虑使用它的name属性来指定。
因此尝试将@ConditionalOnClass(Feign.Builder.class)
修改为@ConditionalOnClass(name = "feign.Feign.Builder")
,
通过名称而不是类型来指定,重新编译项目并启动服务A
,启动成功。
参考
-
springboot启动报sun.reflect.annotation.TypeNotPresentExceptionProxy
https://zhuanlan.zhihu.com/p/462068881 -
ConditionalOnClass not working for Bean methods on Java 8
https://github.com/spring-projects/spring-boot/issues/27846
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2019-01-05 阿里云AHAS应用高可用服务初体验