spring+mybatis启动NoClassDefFoundError异常分析三部曲之三:改spring源码,取详细错误

在上一章《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,这里面有多个工程,本次用到的工程如下图红框所示:

创建这个工程的主要步骤,在《修改和编译spring源码,构建jar(spring-context-4.0.2.RELEASE)》一文中已经说过了,为了编译通过,此处把几处重要的改动再说明一下:

  1. 将官方的spring-beans-4.0.2.RELEASE.jar文件解压,在java/org/springframework/beans/factory/xml目录下,将所有的xsd文件复制到我们工程的同名目录下;
  2. 工程的pom中增加插件,以便打包的时候可以复制xsd文件到jar包,如下:
<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>
  1. GroovyBeanDefinitionReader.java编译未过,本次实战我们不会涉及到Groovy相关的代码,所以此处直接将此文件中的红叉部分注释掉,修改的地方有如下三处:

经过了上面的修改,我们本地的spring-bean工程应该能正常编译的构建程jar包了,开始改源码吧:

根据我们之前的分析,启动失败的位置是在执行AbstractAutowireCapableBeanFactory.createBean的时候,调用populateBean方法抛出了异常,又被try catch将异常捕获处理了,如下图:

所以此次改动就在这里,我们添加更详细的输出,以便在异常的时候可以看到更多的输出信息:

  1. createBean方法会被反复迭代调用,如果每次抛异常都打印信息就太多了,我们不需要这么多,所以加个是否已经打印过异常的标志位,初始值是false,打印一次就改为true:
private static boolean hasErrorPrinted = false;
  1. 把上面截图中的代码改成下图这样,捕获异常后,如果hasErrorPrinted为false,就把异常打印出来,并且将hasErrorPrinted改为true:
  1. 修改完毕了,在工程目录下执行mvn clean package -U,执行成功后在target目录下可以生成最新的spring-beans-4.0.2.RELEASE.jar文件,复制到tomcat的webapp下的lib中替换原有文件,启动tomcat看一下,我们捕获的异常信息被完整的打印出来了,多层迭代导致的StackOverflowError,如下图:

至此,spring启动异常的问题三部曲就全部结束了,除了阅读源码,debug调试,我们还尝试了修改源码,希望此系列的实战能对您今后深入学习spring有所帮助。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏专注数据中心高性能网络技术研发

ubuntu17.04更换主题

1.首先需要安装unity-tweak-tool 2.主题可以去http://www.ubuntuthemes.org/下载    将下载的zip包解压并移动到...

3556
来自专栏埋名

CentOS7安装维护Gitlab

下面是官网复制过来的官方安装方法,最简单的安装,在我大天朝,只能望天兴叹,你可翻墙安装或者略过这里,看下面的。

2913
来自专栏丑胖侠

Spring boot 数据源未配置异常

问题 在使Springboot自动生成的项目框架时如果选择了数据源,比如选择了mysql,生成项目之后,启动会报一下异常: Description: Cann...

3068
来自专栏Petrichor的专栏

ubuntu: scp指令 (远程拷贝)

用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。当你服务器硬盘变为只读 read...

872
来自专栏云计算教程系列

如何在CentOS 7上使用Postgres,Nginx和Gunicorn设置Django

Django是一个功能强大的Web框架,可以帮助您启动Python应用程序或网站。Django包含一个简化的开发服务器,用于在本地测试您的代码,但是对于任何与生...

1243
来自专栏蓝天

automake编译和安装方式说明

作为良好的习惯,建议为第三方库建立专门的目录,目录取名为thirdparty。然后,再在thirdparty下建立名叫src_package,用来存放第三方库的...

823
来自专栏我的小碗汤

不限速 | 百度网盘命令行工具

今天给大家分享一个开源的网盘下载项目BaiduPCS-Go。Go语言编写,仿 Linux shell 文件处理命令的百度网盘命令行客户端。多平台支持, 支持 W...

7493
来自专栏黑泽君的专栏

Eclipse各版本代号一览表以及官网上有很多版本的eclipse,下载哪个版本比较合适呢?

Eclipse的设计思想是:一切皆插件。Eclipse核心很小,其它所有功能都以插件的形式附加于Eclipse核心之上。

3481
来自专栏Brian

Install Django Nginx uWSGI

概述 最近项目需要安装和配置多站点环境,所以把多站点开发环境配置和安装记录下来,帮助其他人少走坑。 安装Python 2.7.x 首先安装一些开发环境基本的包和...

3689
来自专栏琯琯博客

ThinkPHP 连接 sql server 数据库配置

一、ThinkPHP3 的配置 二、ThinkPHP5 的配置 三、原生 pdo sqlsrv 连接 四、原生 sqlsrv 连接 五、总结 PHP 连接 sq...

3868

扫码关注云+社区