NoClassDefFoundError之BeanCreationException异常

前言
根据部门技术要求,同时提高系统的稳定性和易维护性,需要对现有系统进行技术升级改造,在技术改造的过程中难免会遇到一些问题,令我印象比较深刻的就是文章标题所说的BeanCreationException异常,这个看似比较常见的异常出现的原因却和常见的配置文件错误以及包冲突不太一样,本文针对解决这个异常问题做一个简单的总结。

背景
当时项目启动之初,为了使项目能够尽快上线,把部门原有项目的技术框架经过调整移植到本项目中,这套技术框架在业务层和数据持久层中间加了一层数据库的代理层,方便分库分表以及事务控制等操作。由于在生产环境中部门其他项目出现过几次问题,决定把这一层数据库的代理层去掉。本项目没有涉及到分表逻辑,在去掉数据库的代理层时采用了Druid数据库连接池。

异常排查
当整个代理层全部去掉后,在本机启动项目一切正常,等到部署到测试环境启动时却出现了BeanCreationException异常,具体异常信息如下: 

Exception.png

根据异常提示信息仔细检查各配置文件以及JAR包,发现配置文件并没有错误,也没有发现JAR包冲突的情况。检查无误后,尝试把本机的工程WAR包放至LINUX测试环境,启动时出现同样的错误,继续尝试把本机部署好的Tomcat整个放至测试环境,启动时发现一切正常。到这时原因已经很明显了,本机的Tomcat和测试环境的Tomcat配置信息不一样,仔细检查了tomcat的server.xml、context.xml和web.xml并没有什么不同,继续检查startup.sh和catalina.sh文件,发现测试环境的catalina.sh文件中多配置了这些参数信息: 

params.png

最后把这些参数逐个去掉调试,发现当去掉Xss256k这个参数时工程能够正常启动,把Xss参数值改成512k或者1m工程也能正常启动。这个版本改造完成上线的时候把这个参数值设置成了1m,系统改造后运行至今未发现异常。

总结
Xss栈容量(stack size)参数可设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更 多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。Java程序中,每个线程都有自己的Stack Space(堆栈)。这个Stack Space不是来自Heap的分配。所以Stack Space的大小不会受到-Xmx和-Xms的影响,这2个JVM参数仅仅是影响Heap的大小。Stack Space用来做方法的递归调用时压入Stack Frame(栈帧)。所以当递归调用太深的时候,就有可能耗尽Stack Space,爆出StackOverflow的错误。线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时出现溢出的可能性更大,如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会出现内存溢出的错误。
--------------------- 
作者:vipshop_fin_dev 
来源:CSDN 
原文:https://blog.csdn.net/vipshop_fin_dev/article/details/79415011 
版权声明:本文为博主原创文章,转载请附上博文链接!

--------------------

复现问题: 本地修改-Xss104k, 复现该问题;

的确通过以上手段可以解决该问题, 通过定位确实也是抛出了StackOverFlowError 这个错误, 我用的是mybatis-spring 1.1.1这个版本, 我通过升级该版本为1.2.0, 将-Xss调整为104k也可以启动没有问题。

下面来分析下这个问题, 通过追踪发现, 在抛出StackOverFlowError这个错误之后, 被spring作为Throwable捕获到了, 然后此时throw new BeanCreationException(..)这的时候就报NoClassDefFoundError这个错误, 明显是加载BeanCreationException这个类的时候出现了问题, 到此仍然无法解释为什么会出现这个问题。 我classpath下是有这个class定义的, 不应该报这个错误的。

也是只能定位到这里了, 网上有一篇文章写得比较透彻, 为什么StackOverFlowError抛出来之后new BeanCreationException的时候会找不到类定义?spring+mybatis启动NoClassDefFoundError异常分析三部曲之二:定位错误 这里面分析为什么会产生StackOverFlowError, 但是并没有说明为什么会产生NoClassDefFoundError这个问题。

后期有时间会继续跟进这个问题。

猜你喜欢

转载自blog.csdn.net/SkydivingWang/article/details/85341994