刚入职没几天,才开始熟悉项目代码,就已经闻到了代码中充斥着各种异味。真是印证了那句话,你越担心什么,就越来什么。果不其然,没几天就碰到了一个线上的故障,应用当掉了。
现象
应用当掉,CPU和内存耗光 100%。
分析
内存dump
分析DUMP发现内存被某个线程的Mybatis一级缓存PerpetualCache 占用了2.5个多G内存(占总内存86.22%)。
mybatis的一级缓存是事务级别的,一旦事务提交就会清空。因此得出结论,该线程的事务一直未结束和提交。
应用日志和线程堆栈
应用输出的日志中过程信息基本没有,只有SQL语句和接口调用信息。发现有一个线程一直在不停的循环打印重复的日志。故猜测,程序可能进入了死循环。
对比代码发现,还真是。代码中出现了while(true){}语句块,当break的逻辑中漏掉了一个case。而在循环的过程中,某个dao的查询方法不停的被调用,该方法参数使用到了Date类型,而在调用的时候实参使用的是new Date()。真实new Date不能命中缓存,然后不断的查,不断的缓存,导致Mybatis的PerpetualCache内存泄漏。
总结
- 千万不要让应届毕业生独立开发一整套系统
- 警惕代码中出现异味
- while(true){} 要小心