论坛首页 Java企业应用论坛

困扰了近两月的内存泄露问题终于初见眉目了,罪魁祸首:proxool

浏览 33813 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-12-11   最后修改:2008-12-11
困扰了近两月的内存泄露问题终于初见眉目了,罪魁祸首:proxool

生产环境的系统近两个月一直不稳定,过两天内存就会占满,通过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是不是确实有内存泄露...........


-
   发表时间:2008-12-11  
stmt.executeUpdate(sb1.toString()); 

用批量吧?这样提交成本太高了。个人经验批量提交的条数不要太多。多了数据库可能受不了。ORACLE 几万条提交一下还是很快的,MYSQL就慢多了。
0 请登录后投票
   发表时间:2008-12-11  
主要是为了测试连接池的性能,jsp程序当时没怎么考虑优化。:)
0 请登录后投票
   发表时间:2008-12-11  
内存泄露你不用工具去检查, 光靠怀疑? 楼主似乎这么的做法太不科学了。 另外, JAVA的内存收集机制本来就是内存用的差不多才开始收集的。  你现在要做的是, 把在运行的JAVA进程, 使用jmap把堆dump下来, 找个内存heap分析工具, 看看是什么对象泄露了。 有很多免费的工具, 不过, 比较容易找到的, 免费的是 eclipse.org一个项目,可以独立运行, 也可以作为eclise的插件使用----MAT。 你去看看吧。
0 请登录后投票
   发表时间:2008-12-11  
proxool这个连接池还是不错的.我一直用了好几个项目.应该比dbcp强.这个不一定是proxool连接池的问题.你可以换换数据库驱动版本试试.有时候连接池的某个版本跟数据库驱动的某个版本好像是存在问题.
0 请登录后投票
   发表时间: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,以后多探讨探讨
0 请登录后投票
   发表时间:2008-12-11  
lijunjie 写道
proxool这个连接池还是不错的.我一直用了好几个项目.应该比dbcp强.这个不一定是proxool连接池的问题.你可以换换数据库驱动版本试试.有时候连接池的某个版本跟数据库驱动的某个版本好像是存在问题.


我用的mysql官方最新的数据库驱动,同样的驱动,同样的程序,就是proxool有问题,其他两个连接池,确实内存两没怎么上升。

大家有时间的话,也可以测试一下
0 请登录后投票
   发表时间:2008-12-11  
c3p0吧, 我还是觉得这个最信的过,目前, 经过我们几个星期的连续烧烤,与几年的经验, 基本没有问题。 

关于内存问题, JAVA中可以被泄露的问题确实不多, 所以 比起C/C++的排查容易多了, 对于java heap, 你可以使用jmap 直接从生产环境拿下来内leak 分析, 如果很大的内存泄露, 看一眼就知道哪个对象泄露了。

连接POOL的泄露主要表现在, 使用的连接没有归还。要么是已经断开的连接没有释放。 HEAP分析工具对付这些问题切菜才一样。 另外, HEAP 在 DUMP出来的时候, 非live对象可以被排除的, 你看到的结果就是一个干净的, 被引用的对象。
0 请登录后投票
   发表时间:2008-12-11  
这个问题,先从自己程序找原因,去找其他什么连接池都没用。你把auto commit设置为false,那至少执行一定数量的statement(比如说100个)就应该commit一下。
0 请登录后投票
   发表时间:2008-12-11  
c3p0把
我们公司测过,没问题
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics