精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-12-11
最后修改:2008-12-11
生产环境的系统近两个月一直不稳定,过两天内存就会占满,通过jprofiler,jrmc各中方法调试,总是找不到任何原因。 昨天,在做另外一项测试中,终于发现了一个最可能的存在的内存泄露的地方,proxool数据库连接池内存泄露。 测试环境: tomcat6.0 mysql5.0 昨天分别到官方网站下载dbcp,proxool,c3po最新版本。全部配置tomcat下成jndi数据源,连接数都配置成最大300,最小30 jrokit R27.5 testInsertDB.jsp直接通过数据源连接数据库,通过一个事务往数据库每次插入200万条数据库。 <% Connection conn = CourseDBService.getConnection(); Statement stmt = conn.createStatement(); String sb=new String("insert into t_sys_log values('id"); conn.setAutoCommit(false); for(int i=5000000;i<7000000;i++){ StringBuilder sb1=new StringBuilder(sb); sb1.append(i).append("','userId").append(i).append("','userName").append(i).append("',null,'测试课程").append(i).append("',null)"); //System.out.println("-----------------sb="+sb1); stmt.executeUpdate(sb1.toString()); } conn.commit(); stmt.close(); conn.close(); %> tomcat 6启动后占用168M内存, 开始用proxool从100万-300万插入200万数据,tomcat6 占用内存从168M一直涨到1G,在插入完毕后,通过jrmc手动垃圾回收后,通过jrmc观察,时间堆的占用量还在600M左右,怎么也回收不了。 用dbcp从300万-500万插入200万数据,tomcat6 占用内存从168M稍微涨了一点,但是内存变化不大。 用c3p0从500万-700万插入200万数据,tomcat6 占用内存基本没有什么变化。 具体插入的时间我没有太多统计。粗略感觉,好像时间差不多 今天凌晨,服务器上2个tomcat中一个连接池切换成dbcp,到现在内存回收正常,一直很稳定,通过jrmc看内存占用一直稳定在40%左右,在到60%时会回收到40%,最低能回收到30%。 而另外一个依旧用proxool连接池的tomcat,内存占用率从40%一会就升到100%,然后突然回收到40%,然后一会有迅速的达到100%,然后又回收..........,最低只能回收到40% 在线监控中....... 不知道proxool是不是确实有内存泄露........... - 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-12-11
stmt.executeUpdate(sb1.toString());
用批量吧?这样提交成本太高了。个人经验批量提交的条数不要太多。多了数据库可能受不了。ORACLE 几万条提交一下还是很快的,MYSQL就慢多了。 |
|
返回顶楼 | |
发表时间:2008-12-11
主要是为了测试连接池的性能,jsp程序当时没怎么考虑优化。:)
|
|
返回顶楼 | |
发表时间:2008-12-11
内存泄露你不用工具去检查, 光靠怀疑? 楼主似乎这么的做法太不科学了。 另外, JAVA的内存收集机制本来就是内存用的差不多才开始收集的。 你现在要做的是, 把在运行的JAVA进程, 使用jmap把堆dump下来, 找个内存heap分析工具, 看看是什么对象泄露了。 有很多免费的工具, 不过, 比较容易找到的, 免费的是 eclipse.org一个项目,可以独立运行, 也可以作为eclise的插件使用----MAT。 你去看看吧。
|
|
返回顶楼 | |
发表时间:2008-12-11
proxool这个连接池还是不错的.我一直用了好几个项目.应该比dbcp强.这个不一定是proxool连接池的问题.你可以换换数据库驱动版本试试.有时候连接池的某个版本跟数据库驱动的某个版本好像是存在问题.
|
|
返回顶楼 | |
发表时间:2008-12-11
最后修改:2008-12-11
sdh5724 写道 内存泄露你不用工具去检查, 光靠怀疑? 楼主似乎这么的做法太不科学了。 另外, JAVA的内存收集机制本来就是内存用的差不多才开始收集的。 你现在要做的是, 把在运行的JAVA进程, 使用jmap把堆dump下来, 找个内存heap分析工具, 看看是什么对象泄露了。 有很多免费的工具, 不过, 比较容易找到的, 免费的是 eclipse.org一个项目,可以独立运行, 也可以作为eclise的插件使用----MAT。 你去看看吧。
说得不错,老实说,程序问题,我已经用jprofiler测试了两个月了。我是这样测试的,走任何一个单独的功能前,把所有的自己编写的程序的类实例数目保存一遍,执行程序后,又把新的实例数和之前的实例数对比一遍,然后执行jprofiler自带手动垃圾回收,看看哪些实例不能垃圾回收。这样做,虽然工作量大,但是也检测出了一个地方的内存泄露,见我之前的帖子:http://www.iteye.com/topic/263300 经过严查,没有查出程序中存在的问题,然后把spring,hibernate,apache等常用的jar包全部更新的成最新的,内存泄露程序依然存在......... 这次分析出proxool存在问题,并不代表proxool确实存在问题,因为没有看它的源代码来分析,但是对于我来说,是不敢用这个连接池了 sdh5724如果对内存泄露比较熟悉,可以加我id,以后多探讨探讨 |
|
返回顶楼 | |
发表时间:2008-12-11
lijunjie 写道 proxool这个连接池还是不错的.我一直用了好几个项目.应该比dbcp强.这个不一定是proxool连接池的问题.你可以换换数据库驱动版本试试.有时候连接池的某个版本跟数据库驱动的某个版本好像是存在问题.
我用的mysql官方最新的数据库驱动,同样的驱动,同样的程序,就是proxool有问题,其他两个连接池,确实内存两没怎么上升。 大家有时间的话,也可以测试一下 |
|
返回顶楼 | |
发表时间:2008-12-11
c3p0吧, 我还是觉得这个最信的过,目前, 经过我们几个星期的连续烧烤,与几年的经验, 基本没有问题。
关于内存问题, JAVA中可以被泄露的问题确实不多, 所以 比起C/C++的排查容易多了, 对于java heap, 你可以使用jmap 直接从生产环境拿下来内leak 分析, 如果很大的内存泄露, 看一眼就知道哪个对象泄露了。 连接POOL的泄露主要表现在, 使用的连接没有归还。要么是已经断开的连接没有释放。 HEAP分析工具对付这些问题切菜才一样。 另外, HEAP 在 DUMP出来的时候, 非live对象可以被排除的, 你看到的结果就是一个干净的, 被引用的对象。 |
|
返回顶楼 | |
发表时间:2008-12-11
这个问题,先从自己程序找原因,去找其他什么连接池都没用。你把auto commit设置为false,那至少执行一定数量的statement(比如说100个)就应该commit一下。
|
|
返回顶楼 | |
发表时间:2008-12-11
c3p0把
我们公司测过,没问题 |
|
返回顶楼 | |