一个list引发的血案

其实用血案这个有点标题党的感觉,只为博君眼球,套个快过年时的万用语句,来都来了,就看完吧

我们有个业务系统跑了好几年了,一直很稳定,前端时间系统突然开始报内存溢出,分析定位,发现是这段代码的问题:
List<ModelBean> beaList = null;
for(int i=0; i<loop; i++) {
 beanList = service.getBeanList();
 businessProcess(beanList)
}


恩,很简单的一段逻辑,从数据库里查询到一个list,然后处理业务逻辑。
貌似没有什么问题呀!?
确实,在数据量比较小的时候运行的非常安逸,但是!当数据的量级增长问题就来了!
分析一下:
beanList第一次返回1000w数据,开始处理业务逻辑,处理完成,这个时候内存中的beanList由于内存占用过大,直接产生在老年代,而第二次从数据库返回1000w数据的时候,内存不足,GC开始工作,但是发现原来的第一次使用过的beanList由于for块外的引用还存在,还无法回收内存,开始徒劳的fullGC,结果就out of memory了。

问题分析出来了,解决方法也就很简单了:
for(int i=0; i<loop; i++) {
 List<ModelBean> beanList = service.getBeanList();
 businessProcess(beanList)
}

将beanList的生命周期封闭在for循环内,问题迎刃而解。

有人也许会说,这么基础的问题,值得你写篇文章来说道吗?其实不然,最简单的问题往往是我们最容易忽视的问题,解决问题一般都是容易的,困难是查找和分析问题。开始学习effective java就看到过,把local variable的生命周期尽可能封闭在其使用周期结束内,代码写得时间久了,越来越随心所欲,久而久之就忘记了很多基础的要求,写下来,算是对自己的一个警醒吧。

猜你喜欢

转载自zenghuiss.iteye.com/blog/2410232