JVMST109: Insufficient space in Javaheap to satisfy allocation request错误的处理
环境:aix5.3L+weblogic8.1+ibm jdk1.42 6g内存,给weblogic的内存为1536m.
错误:
JVMST109: Insufficient space in Javaheap to satisfy allocation request
java.lang.OutOfMemoryError (简称oom)
发生情况: 当一报表结果集8万行的时候,页面只取100行的时候报异常,生产库服务器停掉了. 为查出原因,找了很多相关资料,其中有谈到ibm jdkjdk1.4的垃圾回收机制与sun jdk1.4机制的异同.没有时间去考察这些异同的真实性.另这类错误,既然是大内存的分配与释放,从代码本身解决才是最根本的.
下面就我的有关实验记录一下.
[@more@]经实验证实在p4 双核3.2g 3.2g的机器上分配一个stringBuffer的对象最大值为210 000 000左右.超过这个值会报oom错误.
根据这一结论,我对原错误进行猜想,因为取数据库结果集时指定了每页行大小,按正常情况,还不会报oom错误.
进一步分析原码:
DataSet dset = erpm1.executeQueryToDataSet(sqlSelect);
rowCount = dset.getRowCount();
DataSet是离线结果集,既然是离线的,他当然会把所有东西包在里面,当一结果集超大的时候(比如8万,其实测试时,当结果集大于2万条时,就顶不住了),不报oom才怪呢?
所以只有把这个地方处理好了,就可以了. 简单地说,就是首先求总行数,然后依据条件写出分页sql,不要一次性装载所有数据。否则白天服务器当机,看人家瞧你!
后记:
由这个错误,我想起了
离线处理数据库,好处:即时的在基类代码里处理与数据库资源的释放问题,使得代码简洁.用空间换取了时间,赢得了效率.但同时也带来了潜在的问题,大量的内存被消耗了. 虽说java的垃圾回收机制比较先进,而且还在进步,但当遇到这种超大结果集的时候,就暴露出了很大的问题,一下子分配过多,就oom了.
而联机处理的resultSet就没有这样的问题(但是,如果取数过大,会占用数据库内存从而引发问题(一般在应用端出问题的,肯定先经过数据库端,应该说数据库可以运行通过),所以,在取数时,切记用分页处理,不要一次性全部取出,尤其是大表),他不会将所有的结果全部装进内存,只在你取的时候,从数据库读出来,他的缺点是总头至尾始终占用数据库资源.并且在使用完后,一定要手工释放资源,不能自动回收.这样使代码看起来显得臃肿.
个人觉得,对于大型项目中基类中的东西,还是用底层的东西较好,尽量避免大内存的分配与释放,提高效率才是解决问题的根本.在后面的应用层,当然还是尽量封装好的,毕竟不是每个开发员都能写出优雅的代码.
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/11419868/viewspace-1009007/ ,如需转载,请注明出处,否则将追究法律责任。