SpringBoot突报java.lang.NoSuchFieldError分析
SpringBoot项目,引了一个内部的工具包,竟然导致启动失败,报找不到freemarker Configuration类的一个属性,网上的解法都大同小异,最终用了自己的办法解决,花点时间记录下来,希望能帮助到别人。
关键词:SpringBoot,AutoConfiguration,freemarker,NoSuchFiledError
问题背景
最近在开发过程中由于要用到公司内部的一个工具类,所以添加了common-util.jar到工程的maven依赖中,功能开发完了,打算本地调试一下,但悲剧的是应用启动失败了。查看堆栈信息,并没有我新添加的代码,是Spring初始化失败了,堆栈信息如下:

初步分析
对照着堆栈来看,错误很明确,就是在运行时缺少freemarker.template.Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS 这个field导致,但是怎么解决呢?度娘上基本都是下面这两种解决办法:

图片来源于https://www.cnblogs.com/geekdc/p/9243069.html
我并没有采用这两种办法,因为这并不是一个新搭建的工程,而且我这次也没有做过任何版本升级,唯一的可能就是引入的新jar包有问题。
再看异常堆栈
从堆栈来看是缺少了一个Field导致,那什么情况下会造成这种情况呢,我第一时间猜测应该是jar包冲突了,因为之前遇到过一次,有兴趣的可以看这里,我查看了新引入jar包内部的pom文件,确实是依赖了freemarker(2.3.16)的jar包,而且scope是compile,就这样,这个低版本的freemarker被传递依赖进来了,至于最终使用哪个,就由maven的仲裁机制决定了,很明显我这个工程最终用了老版本,所以导致运行时找不到Field,解决方案很简单,使用exclusion将老版本的freemarker排除就好了。一般故事到这儿就结束了,但是我这个人手贱,偏要看看项目以前依赖的freemarker是什么版本的,结果看完又不能按时睡觉了(题外话:白天老是这事那事,晚上才有时间写代码)。
意外收获
我使用mvn dependency:tree将所有依赖都输出到文本文件里,然后搜索freemarker,结果意外的发现居然没有依赖freemarker,这是什么情况,刚刚不是还j说ar包冲突了吗,难道是自我冲突了?
一时间没有了头绪,想百度都不知道关键字写什么。一般这个时候我会点根烟开始复盘,从头到尾反复看案发现场,总能发现蛛丝马迹。终于灵光一下,我脑子里闪过这么一段话“之前没有freemarker.jar的时候不报错,现在有了也应该不报错才对,除非SpringBoot具有自动发现功能,可以实现组件可插拔”,就这样,我尝试搜索“SpringBoot自动发现”,看看百度给我的结果:

我很自然的过滤了第二条搜索内容,因为我知道那不是我想要的,我内心想表述的其实是“自动转配、自动配置”。
根因分析
了解了自动装配的大概原理后,我梳理出了这次启动失败的根本原因,如下:
- SpringBoot启动的时候触发自动配置;
- spring-boot-autoconfigure-1.5.11.RELEASE.jar\META-INF\spring.factories里面是需要自动配置的Bean,里面就有FreeMarkerAutoConfiguration;
- 自动配置一般会有一些约束条件,满足条件才会自动配置,条件通过@Condition***这类注解来声明;
- FreeMarkerAutoConfiguration的自动配置约束条件为@ConditionalOnClass({freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class}),意味着只有freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class这两个类都存在的时候才会自动配置;
- 如果第四步满足条件,最终会触发FreeMarkerConfigurationFactory.newConfiguration这个方法,这个方法内部用到了Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS这个Field,它来源于freemarker.jar,就是堆栈中报NoSuchFiledError的主角;
- 如果第四步不满足条件,就不触发FreeMarkerAutoConfiguration的自动配置,进而不会用到Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS这个Field;
FreeMarkerConfigurationFactory来源于spring-context-support-4.3.15.RELEASE.jar,这个jar包之前就依赖了,而Configuration来源于freemarker.jar,是common-util.jar传递依赖进来的,所以正好满足了上面的第四步,进而触发了第五步,最终导致SpringBoot启动失败。
汇总解决办法
通过上面的一些分析,我认为这个问题一共有以下几种办法:
- 如果你的项目中没有用到freemarker的话可以禁用freemarker的自动配置,像初步分析那里提到的;
- 升级freemarker到高版本;
- 像我遇到的问题一样,确实不需要freemarker功能,可以将freemarker.jar排除;
总结
虽然是个很小的问题,但是解决过程确实让我收获不少,之前对于SpringBoot只停留在简单使用阶段,通过这次排查过程,也算是了解了SpringBoot自动配置的大体思想,这种可插拔的设计真的是非常巧妙。
如果觉得有用,请您点个推荐。
参考资料:
https://www.cnblogs.com/nijunyang/p/12051770.html
https://blog.csdn.net/ZYC88888/article/details/84245127
SpringBoot突报java.lang.NoSuchFieldError分析的更多相关文章
- springboot启动异常java.lang.NoSuchFieldError: DEFAULT_INCOMPATIBLE_IMPROVEMENTS
解决办法一 yml或者Properties文件中配置 spring.freemarker.check-template-location=false 解决办法二 @SpringBootApplicat ...
- 【原创】大叔问题定位分享(2)spark任务一定几率报错java.lang.NoSuchFieldError: HIVE_MOVE_FILES_THREAD_COUNT
最近用yarn cluster方式提交spark任务时,有时会报错,报错几率是40%,报错如下: 18/03/15 21:50:36 116 ERROR ApplicationMaster91: Us ...
- java.lang.NoSuchFieldError: VERSION_2_3_0 报错解决方案
java.lang.NoSuchFieldError: VERSION_2_3_0 at org.apache.struts2.views.freemarker.FreemarkerManager.c ...
- springBoot集成Elasticsearch抛出Factory method 'restHighLevelClient' threw exception; nested exception is java.lang.NoSuchFieldError: IGNORE_DEPRECATIONS
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restHighLeve ...
- jenkins执行构建任务报错之java.lang.NoSuchFieldError: DEFAULT_USER_SETTINGS_FILE
在执行创建工作空间时候,创建不成功,出现错误?? ......... java.lang.NoSuchFieldError: DEFAULT_USER_SETTINGS_FILE ......... ...
- java报错:Exception in thread "main" java.lang.NoSuchFieldError: INSTANCE
Exception in thread "main" java.lang.NoSuchFieldError: INSTANCE at org.apache.http.conn.ss ...
- java.lang.NoSuchFieldError 异常原因
一般都是因为 class 或 jar 包重复 导致的 , 也有可能是编译器的问题. 我碰到的问题是,在项目api 接口jar包里定义了一个Config.java,然后在业务层service 项目 的相 ...
- Java.lang.NoSuchFieldError: INSTANCE异常
解决方案: java.lang.NoSuchFieldError: INSTANCE异常. 1.jar包重复了. 2.版本还不相同,如果包的版本不同也会报相应的错,不过一般情况自己导入的jar包主要看 ...
- java.lang.NoSuchFieldError: RAW_XML_FILE_HEADER,调用XWPFTemplate动态合并生成一个新的docx文档时报错
在使用 org.apache.poi 对office文件 根据表单内容和已上次的附件 动态合并成一个新的文档时,本地调试完全ok 但是发布倒Linux环境上就老是报这个错误java.lang.NoS ...
随机推荐
- 网站爬取-案例一:猫眼电影TOP100
今天有小朋友说想看一下猫眼TOP100的爬取数据,要TOP100的名单,让我给发过去,其实很简单,先来看下目标网站: 建议大家都用谷歌浏览器: 这是我们要抓取的内容,100个数据,很少 我们看一下页面 ...
- github傻瓜的食用方法
配置Git 首先在本地创建ssh key: 1 $ ssh-keygen -t rsa -C "your_email@youremail.com" 后面的your_email@yo ...
- 吴裕雄--天生自然 R语言开发学习:使用键盘、带分隔符的文本文件输入数据
R可从键盘.文本文件.Microsoft Excel和Access.流行的统计软件.特殊格 式的文件.多种关系型数据库管理系统.专业数据库.网站和在线服务中导入数据. 使用键盘了.有两种常见的方式:用 ...
- POJ3264 Balanced Lineup [RMQ模板]
题意:有n头牛,输入他们的身高,求某区间身高的极值的差(max-min), 用RMQ模板,同时构造求极大值和极小值的两个数组. //poj3264 #include <iostream> ...
- java内部类基础知识
一.java内部类具体分四大类 1.成员内部类 2.静态内部类 3.局部内部类 4.匿名内部类 1.成员内部类 :作为类的成员,存在于类中 //成员内部类可以调用外部类的所有 ...
- 翻转链表和k个一组翻转以及两两反转
一.输入一个链表,输出反转后的链表. 非递归实现: # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.v ...
- Redis 总结精讲 看一篇成高手系统
转自:https://blog.csdn.net/hjm4702192/article/details/80518856 本文围绕以下几点进行阐述 1.为什么使用redis2.使用redis有什么缺点 ...
- JavaScript replace() 方法+字符子集介绍(*)
重点两部分知识点 1.javascript replace()函数用法 以下replace用法转载自w3cSchool:http://www.w3school.com.cn/jsref/jsref_r ...
- Pytorch collate_fn用法
By default, Dataloader use collate_fn method to pack a series of images and target as tensors (first ...
- 华为VS小米 营销手段有待继续强化
营销手段有待继续强化" title="华为VS小米 营销手段有待继续强化"> 对于大多数来说,希望看到强者愈强的戏码.比如:NBA里的N场连胜.苹果帝国千秋万载一统 ...