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 ...
随机推荐
- The file named error_log is too large
The file named errorlog is too large */--> The file named errorlog is too large 1 Problem One day ...
- python、anaconda、jupyter notebook、pycharm、spyder
说明: 1.anaconda把任何东西都当做包来管理. 2.anaconda本省集成了python和conda.spyder.numpy等. 3.pip只用于python,conda可用于多种语言. ...
- django框架进阶-AJAX-长期维护
################## 预备知识---json ####################### 预备知识,json 什么是json?这是一种数据格式,和语言没有关系, 为什么 ...
- Users组权限Win7虚拟机继承Administrator的个性化设置
在administrator账号下进行的模板设置,配置文件保存在“C:\Documents and Settings\Administrator”文件夹下的profile里面,但是创建的用户虚拟机获取 ...
- smarty应用1 之 模板进行数学运算,保留小数位数
例子1 乘法除法运算: 1格式:{$number|number_format} 保留小数点后2位小数. {$v/$total*100|string_format:"%0.2f"|c ...
- php单例模式的常见应用场景
单例模式(Singleton)也叫单态模式,是设计模式中最为简单的一种模式,甚至有些模式大师都不称其为模式,称其为一种实现技巧,因为设计模式讲究对象之间的关系的抽象,而单例模式只有自己一个对象,也因此 ...
- Win32双缓冲画图原理
网上有许多文章讲述了如何使用Visual C++程序实现双缓冲,都是用C++面向对象语言写的,可能对很多没有接触过面向对象语言的C语言初学者来说理解起来有些困难,并且有些好心人也只是把源代码贴上去,不 ...
- [洛谷P3403] 跳楼机
题目传送门 套路题,同余最短路. 先只考虑y.z进行连边,再在mod x的意义下进行计算. 这里的“距离”dis[i]指的是,在所有满足a mod x=i的a里,能到达的最小的a是多少. 显然只要能到 ...
- 测试一个数字是否等于 NaN
ES6提供了一个新的 Number.isNaN() 函数,这是一个不同的函数,并且比老的全局 isNaN() 函数更可靠.
- Python实现简单Web服务器
实验楼教程链接: https://www.shiyanlou.com/courses/552/labs/1867/document http原理详解(http下午茶): https://www.kan ...