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 ...
随机推荐
- String的compareTo用法
String的compareTo其实就是依次比较两个字符串ASC码.如果两个字符的ASC码相等则继续后续比较,否则直接返回两个ASC的差值.如果两个字符串完全一样,则返回0.来看一下代码. publi ...
- 统计学方法(t-检验)
数据出来要做几件事:首先判断数据是否符合正态分布,如果符合的话,就要进行t-检验,那么进行t-检验的作用在哪呢? t-检验主要用于样本含量较小(例如n<30),总体标准差σ未知的正态分布 htt ...
- Web前端性能
6.1前端性能示例 性能测试工具: Apache Benchmark(ab)得到的响应时间仅为从请求发出开始到接收到HTML的最后一个字节所消耗的全部时间.ab命令行如下: ab -c [并发用户数] ...
- python djangjo完整的实现添加的实例
实现:点击添加实现模态对话框,添加数据并显示. urls.py from django.conf.urls import url from django.contrib import admin fr ...
- svn merge Property conflicts
svn merge代码的时候,出现Property conflicts的解决方案.可以参考:http://stackoverflow.com/questions/23677286/conflict-w ...
- maven工程根项目运行ok但是子项目就报错的解决办法
正常启动没错 项目出现问题 maven工程根项目运行ok但是子项目就报错 报错信息是xxxx没有创建 解决办法 原来是子项目的依赖少了 没有配置1.8 所以会出现莫明其妙的bug
- struts2和springmvc性能比较2
我们用struts2时采用的传统的配置文件的方式,并没有使用传说中的0配置.spring3 mvc可以认为已经100%零配置了(除了配置spring mvc-servlet.xml外). Spring ...
- Elays'Blog
文章导航 阴影的重要意义 阴影是光线被阻挡的结果,它能够使场景看起来真实很多,可以让观察者获得物体之间的空间位置关系.如下图所示: 图1 可以看到,有阴影的时候能够更容易的看出立方体是悬浮在地板上的. ...
- Java遍历文件夹的两种方法(非递归和递归)
import java.io.File; import java.util.LinkedList; public class FileSystem { public static int num ...
- Python的Flask框架开发RESTful API
web框架选择 Django,流行但是笨重,还麻烦,人生苦短,肯定不选 web.py,轻量,但据说作者仙逝无人维护,好吧,先pass tornado,据说倡导自己造轮子,虽然是facebook开源的吧 ...