欢迎访问我的GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):
https://github.com/zq2599/blog_demos
- 在上一章《spring+mybatis启动NoClassDefFoundError异常分析三部曲之二:定位错误》中,我们通过打断点的方式,在spring初始化时创建bean的位置单步执行代码,定位到了应用启动失败的原因是由于AbstractAutowireCapableBeanFactory.createBean方法被多层嵌套式调用从而导致了栈内存被耗光,抛出了StackOverflowError异常,但由于doCreateBean方法捕获异常并抛出新的异常,导致启动的输出信息中看不到原始的错误堆栈,本章我们一起来修改并编译spring源码,使得错误发生的时候及时打印出有效的堆栈信息,以便我们定位问题;
- 关于修改和编译spring源码的方法,您可以参照《修改和编译spring源码,构建jar(spring-context-4.0.2.RELEASE)》,此处我们修改的不是spring-context,而是spring-bean,如果读者您觉得准备一个修改和编译spring-bean源码的环境太费时太麻烦,也可以从我的git上直接下载可运行的工程,地址是:git@github.com:zq2599/blog_demos.git,这里面有多个工程,本次用到的工程如下图红框所示:
![这里写图片描述 这里写图片描述](https://ucc.alicdn.com/images/user-upload-01/img_convert/54c9597e4095acafff5d98edb2746f17.png?x-oss-process=image/resize,w_1400/format,webp)
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-resource</id>
<phase>generate-resources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xsd</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
- GroovyBeanDefinitionReader.java编译未过,本次实战我们不会涉及到Groovy相关的代码,所以此处直接将此文件中的红叉部分注释掉,修改的地方有如下三处:
![这里写图片描述 这里写图片描述](https://ucc.alicdn.com/images/user-upload-01/img_convert/9f4f83940e2d1d04efa0b8fa2a30a2a7.png?x-oss-process=image/resize,w_1400/format,webp)
![这里写图片描述 这里写图片描述](https://ucc.alicdn.com/images/user-upload-01/img_convert/a41fb49c01079f973c8336dd1fc21c55.png?x-oss-process=image/resize,w_1400/format,webp)
![这里写图片描述 这里写图片描述](https://ucc.alicdn.com/images/user-upload-01/img_convert/136cf79206f06e399c85fe36081998d1.png?x-oss-process=image/resize,w_1400/format,webp)
- 经过了上面的修改,我们本地的spring-bean工程应该能正常编译的构建程jar包了,开始改源码吧:
- 根据我们之前的分析,启动失败的位置是在执行AbstractAutowireCapableBeanFactory.createBean的时候,调用populateBean方法抛出了异常,又被try catch将异常捕获处理了,如下图:
![这里写图片描述 这里写图片描述](https://ucc.alicdn.com/images/user-upload-01/img_convert/cd9b16dd0467268051f8871cb7915be9.png?x-oss-process=image/resize,w_1400/format,webp)
- 所以此次改动就在这里,我们添加更详细的输出,以便在异常的时候可以看到更多的输出信息:
- createBean方法会被反复迭代调用,如果每次抛异常都打印信息就太多了,我们不需要这么多,所以加个是否已经打印过异常的标志位,初始值是false,打印一次就改为true:
private static boolean hasErrorPrinted = false;
- 把上面截图中的代码改成下图这样,捕获异常后,如果hasErrorPrinted为false,就把异常打印出来,并且将hasErrorPrinted改为true:
![这里写图片描述 这里写图片描述](https://ucc.alicdn.com/images/user-upload-01/img_convert/146d6648791de76c7d3d5fdfd1d8d7b5.png?x-oss-process=image/resize,w_1400/format,webp)
- 修改完毕了,在工程目录下执行mvn clean package -U,执行成功后在target目录下可以生成最新的spring-beans-4.0.2.RELEASE.jar文件,复制到tomcat的webapp下的lib中替换原有文件,启动tomcat看一下,我们捕获的异常信息被完整的打印出来了,多层迭代导致的StackOverflowError,如下图:
![这里写图片描述 这里写图片描述](https://ucc.alicdn.com/images/user-upload-01/img_convert/975a12698b7a3d81c8d32d7b08d7e9c4.png?x-oss-process=image/resize,w_1400/format,webp)
- 至此,spring启动异常的问题三部曲就全部结束了,除了阅读源码,debug调试,我们还尝试了修改源码,希望此系列的实战能对您今后深入学习spring有所帮助。
欢迎关注阿里云开发者社区博客:程序员欣宸
学习路上,你不孤单,欣宸原创一路相伴...