`
dreamlakyxy
  • 浏览: 25788 次
  • 来自: ...
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

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

阅读更多
困扰了近两月的内存泄露问题终于初见眉目了,罪魁祸首: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是不是确实有内存泄露...........


-
分享到:
评论
40 楼 airport 2009-01-19  
proxool 好像是我比较三个连接池后选用的最好的一个。

要是本身有问题,不至于现在才发现。
39 楼 lzb7213 2009-01-15  
sdh5724 写道
c3p0吧, 我还是觉得这个最信的过,目前, 经过我们几个星期的连续烧烤,与几年的经验, 基本没有问题。 

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

连接POOL的泄露主要表现在, 使用的连接没有归还。要么是已经断开的连接没有释放。 HEAP分析工具对付这些问题切菜才一样。 另外, HEAP 在 DUMP出来的时候, 非live对象可以被排除的, 你看到的结果就是一个干净的, 被引用的对象。

C3P0 不行 你可以google下 对连接的释放速度跟不上 对于并发数量很多的系统就不行 一般系统还是可以的  proxool对连接的管理还是可以的 在大并发量下 对连接的管理很好
38 楼 dreamlakyxy 2008-12-18  
sg552 写道
dreamlakyxy 写道
困扰了近两月的内存泄露问题终于初见眉目了,罪魁祸首:proxool

生产环境的系统近两个月一直不稳定,过两天内存就会占满,通过jprofiler,jrmc各中方法调试,总是找不到任何原因。

-


能否说说你是如何使用JProfiler的??

按照我的经验,它是最擅长查这个的。


jrmc我用的也不是特别熟。

就是通过jrmc的console和memleak检查的,通过console检查内存,线程,cpu的使用状况,通过memleak检查类实例和说占用的heap的大小,没过一段时间,检查一些,哪些类实例增加的特别大,就右键选择,进行堆栈分配跟踪

不知道sg552 有什么好的建议?
37 楼 dreamlakyxy 2008-12-18  
Xsen 写道
congjl2002 写道
我的系统中也有内存泄漏的问题,但是现在没时间好好查,不过有一次我用jprofer简单查了一下,发现String这个占用内存很大,你是这样的吗?为什么呢


可能是taglib问题: http://xsen.iteye.com/blog/159218



我把http://xsen.iteye.com/blog/159218的原文引过来了了
引用

最近遇到了Java系统内存泄漏的问题,翻了几遍代码也没看出来问题来。最后怀疑是开源控件的问题,首先想到了Quartz,但最终也没发现太多问题。也看过JProfiler监控的情况,除了String对象占用内存较多以外,也没发现任何其他异常数量的对象。
最后还是老大用jmap和jhat查出了问题,罪魁祸首是taglib,因为我们的页面中使用了taglib,而传入的值是一个拼接了当前时间数的字符串(一个url),而taglib对这些变量有缓存功能,所以每次页面请求taglib都会缓存一个url字符串。具体是放在一个Map类型的静态变量中的,所以当系统运行3天左右内存就爆满了。。。


我也是发现String占用量特别大,经过memleak检查,是发现taglib占用了很多,但是没想到原因。我们也是每个url+一个当前时间的字符串,难道这个影响?

那怎么改呢,很多情况下,如果不拼时间字符串的话,都会缓存的

36 楼 Xsen 2008-12-17  
congjl2002 写道
我的系统中也有内存泄漏的问题,但是现在没时间好好查,不过有一次我用jprofer简单查了一下,发现String这个占用内存很大,你是这样的吗?为什么呢


可能是taglib问题: http://xsen.iteye.com/blog/159218
35 楼 sg552 2008-12-17  
dreamlakyxy 写道
困扰了近两月的内存泄露问题终于初见眉目了,罪魁祸首:proxool

生产环境的系统近两个月一直不稳定,过两天内存就会占满,通过jprofiler,jrmc各中方法调试,总是找不到任何原因。

-


能否说说你是如何使用JProfiler的??

按照我的经验,它是最擅长查这个的。
34 楼 dreamlakyxy 2008-12-16  
robbin 写道
dreamlakyxy 写道
解决方案有:
1. nginx采用ip_hash,同一个ip段,定位到同一个tomcat上,
2. 禁用session。
但是我把公共引用的jsp页面设置了 <%@ page session="false" %> ,好像还是能生成session。

现在准备采用HttpSessionListner,一生成session,就把他销毁。

不知道大家还有没有更好的办法,来完全禁用session。tomcat有配置完全禁用session的地方吗?


web.xml里面可以设置session过期时间,你可以把过期时间改成1分钟试试看。

恩,也是一种方法
33 楼 robbin 2008-12-16  
dreamlakyxy 写道
解决方案有:
1. nginx采用ip_hash,同一个ip段,定位到同一个tomcat上,
2. 禁用session。
但是我把公共引用的jsp页面设置了 <%@ page session="false" %> ,好像还是能生成session。

现在准备采用HttpSessionListner,一生成session,就把他销毁。

不知道大家还有没有更好的办法,来完全禁用session。tomcat有配置完全禁用session的地方吗?


web.xml里面可以设置session过期时间,你可以把过期时间改成1分钟试试看。
32 楼 dreamlakyxy 2008-12-16  
解决方案有:
1. nginx采用ip_hash,同一个ip段,定位到同一个tomcat上,
2. 禁用session。
但是我把公共引用的jsp页面设置了 <%@ page session="false" %> ,好像还是能生成session。

现在准备采用HttpSessionListner,一生成session,就把他销毁。

不知道大家还有没有更好的办法,来完全禁用session。tomcat有配置完全禁用session的地方吗?
31 楼 dreamlakyxy 2008-12-16  
经分析,session确实可能引起问题。我们程序完全没有用session,也没用关闭session。
一个nginx随机分发到两个tomcat上面,

假设一个极端的情况下,一个用户一个小时,点击了200万个不同的页面,每次通过nginx分发到不同tomcat上,
T1(tomcat1),T2(tomcat2),收到url的顺序是t1,t2,t1,t2,t1,t2 ..........

1. t1判断是New url,生成一个session,同时置sessionid与客户端的会话cookie中
2. t2判断是New url,同时判断客户端会话cookie的中的sessionid,不是t2自己生成的id,于是生成一个新session,同时置sessionid与客户端的会话cookie中
3. t1收到url,同时判断客户端会话cookie的中的sessionid,不是t1自己生成的id,于是生成一个新session,同时置sessionid与客户端的会话cookie中
.
.
.

所以在一个小时内,t1,t2分别生成了100万个session,如果session的默认过期时间为1个小时,则,这个100万个session都存在内存中.


所以session应该是其中的一个原因,但还不是关键原因。
30 楼 dreamlakyxy 2008-12-15  
nickxu 写道
xucons 写道
很有可能是THREAD LOCAL引起的,要注意threadlocal的使用要清空。

我想问一下ThreadLocal的内容不是线程结束后自动被jvm回收吗?需要手动清空?

我查了一下,好像不需要的
29 楼 nickxu 2008-12-15  
xucons 写道
很有可能是THREAD LOCAL引起的,要注意threadlocal的使用要清空。

我想问一下ThreadLocal的内容不是线程结束后自动被jvm回收吗?需要手动清空?
28 楼 puroc 2008-12-14  
既然proxool的问题,就还他个清白吧。改一下帖子的标题吧。他醒目了。
27 楼 javaeyebird 2008-12-12  
skzr.org 写道
无论是sun、ibm还是eclipse的编译器,全都会自动生成StringBuilder和append,和手工写的是完全一样的

这一点不敢同意:并不是sun、ibm、和eclipse的编译器了

我只为这个问题研究过手写StringBuilder的append和+ 在sun的JDK 5.0中生成的字节码 得出来实际上最后生成的直接码两者完全一致。并不是编译器的原因了

生成字节码就是编译器的事啊

这三家的编译器javac(就是.java->.class)我都仔细验证过字节码
字符串+都是得到调用StringBuilder.append的字节码,而不是调用String.concat
26 楼 dreamlakyxy 2008-12-12  
到现在为止,又平稳的运行一天了。
通过jrmc查看:
tomcat1 线程数66,没有死锁,
tomcat2 线程数70,没有死锁
25 楼 dreamlakyxy 2008-12-12  
robbin 写道
等Tomcat内存泄漏现象明显的时候 kill -3 pid
等tomcat已经死掉的时候先不要着急重起,再次kill -3 pid

让他dump整个线程堆栈,看看有没有大量被BLOCKED状态的线程,观察一下线程状态。


恩,我试试。

刚才分析堆栈,图片如下:



发现可能tomcat session创建了很多ConcurrentHashMap实例,难道竟然是session影响?

我们程序是不用session的,准备在common.jsp中加上 <%@ page session="false" %>

刚刚看了一个帖子,觉得很有理,大家以为然否?
http://sdyouyun.iteye.com/blog/146275


24 楼 robbin 2008-12-12  
等Tomcat内存泄漏现象明显的时候 kill -3 pid
等tomcat已经死掉的时候先不要着急重起,再次kill -3 pid

让他dump整个线程堆栈,看看有没有大量被BLOCKED状态的线程,观察一下线程状态。
23 楼 dreamlakyxy 2008-12-12  
事务配置如下:
<bean id="txProxyTemplate" abstract="true"
		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<property name="transactionManager" ref="transactionManager" />
		<property name="transactionAttributes">
			<props>
				<prop key="save*">PROPAGATION_REQUIRED</prop>
				<prop key="update*">PROPAGATION_REQUIRED</prop>
				<prop key="delete*">PROPAGATION_REQUIRED</prop>
				<prop key="remove*">PROPAGATION_REQUIRED</prop>
				<prop key="add*">PROPAGATION_REQUIRED</prop>
				<prop key="modify*">PROPAGATION_REQUIRED</prop>
				<prop key="calculate*">PROPAGATION_REQUIRED</prop>
				<prop key="process*">PROPAGATION_REQUIRED</prop>
				<prop key="noTransaction*">PROPAGATION_NOT_SUPPORTED</prop>
				<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
			</props>
		</property>
	</bean>


然后所有的manager bean的配置都是类似下面的代码
<bean id="forumAreaManager" parent="txProxyTemplate">
		<property name="target">
			<bean
				class="com.fjt.forum.service.impl.ForumAreaManagerImpl">
				<property name="forumAreaDao" ref="forumAreaDao" />
				<property name="commonTagDao" ref="commonTagDao" />
			</bean>
		</property>
	</bean>


服务器宕机的时的表现是,两个tomcat的java进程所占cpu都是400%左右,用linux top命令看的。
这个时候把catalina.out日志备份后删除,重启tomcat。
事后分析catalina.out日志,发现没有什么特殊的地方,没有不能创建mysql连接、connection消耗尽的情况,都是常规的日志。其中关于jrockit垃圾回收的日志有下面几条
[INFO ][memory ] 35315.048-35332.522: GC 611536K->512771K (920128K), sum of pauses 183.922 ms
***其他的正常日志

[INFO ][memory ] 35359.423: parallel nursery GC 902118K->454118K (920128K), 1766.494 ms
***其他的正常日志

[INFO ][memory ] 35470.454: parallel nursery GC 902118K->511718K (920128K), 3117.067 ms
***其他的正常日志


22 楼 dreamlakyxy 2008-12-12  
robbin 写道
看起来ConcurrentHashMap对象实例的数量格外的高。你应该检查一下应用程序在什么地方大量用到了这个类。推荐你看看:

http://www.iteye.com/post/676536
http://www.iteye.com/topic/231670

这两个帖子提到在高并发情况下ConcurrentHashMap的锁定问题,有可能是Spring事务配置不合理导致的。


恩,我研究研究这两个帖子。

首先可以肯定是,自己编写的程序没有直接用到过ConcurrentHashMap。
可能用到ConcurrentHashMap的地方,也许是spring,hibernate等类库。
我检查检查

robbin大侠出手了,谢谢谢谢。

21 楼 robbin 2008-12-12  
看起来ConcurrentHashMap对象实例的数量格外的高。你应该检查一下应用程序在什么地方大量用到了这个类。推荐你看看:

http://www.iteye.com/post/676536
http://www.iteye.com/topic/231670

这两个帖子提到在高并发情况下ConcurrentHashMap的锁定问题,有可能是Spring事务配置不合理导致的。

相关推荐

    proxool-0.9.1.jar,proxool-cglib.jar

    标题中的"proxool-0.9.1.jar"和"proxool-cglib.jar"是两个重要的Java档案文件,它们是Proxool项目的组件。Proxool是一个开源的数据库连接池解决方案,它允许开发者在Java应用程序中高效地管理数据库连接。数据库连接...

    proxool-0.9.0RC3

    **proxool-0.9.0RC3:一个高效开源的数据库连接池** 在IT行业中,数据库连接池是提升应用程序性能的重要工具。其中,`proxool`是一个备受开发者青睐的开源连接池解决方案,版本号为0.9.0RC3。这个版本提供了稳定且...

    proxool-0.9.1.jar

    `proxool-0.9.1.jar` 是一个Java库,它提供了名为Proxool的数据库连接池服务。数据库连接池在多用户、高并发的Web应用中扮演着重要角色,因为它有效地管理了数据库连接,避免了频繁创建和关闭连接带来的性能开销。...

    proxool.jar包,proxool连接池用到的两个jar包

    `proxool.jar`是Proxool数据库连接池的实现库,它是Apache软件基金会的一个开源项目。Proxool是一个轻量级、高效的数据库连接池解决方案,它允许开发者在Java应用程序中管理数据库连接,以提高性能并减少资源消耗。...

    Proxool.jar

    同时,监控Proxool的运行状态,定期检查日志,以便及时发现并解决可能出现的连接泄漏或资源耗尽问题。 在压缩包的`lib`目录下,如果没有其他文件,那么可能假设开发者已经将所有必要的库文件都包含在项目中。通常,...

    proxool配置详解

    标题中的“proxool配置详解”指的是Proxool,这是一个开源的数据库连接池管理工具,它在Java应用程序中用于管理和优化数据库连接。Proxool的主要作用是提高应用性能,通过复用已建立的数据库连接,避免频繁创建和...

    proxool连接池jar包

    3. **监控功能**:独特的监控机制使得开发者可以实时查看连接池的状态,如当前连接数、空闲连接数、等待连接数等,这有助于及时发现并解决连接泄漏问题。 4. **诊断能力**:当系统出现异常时,Proxool能提供详细的...

    Hibernate+Proxool配置

    由于项目需求的需要,我们引入了连接池。...我们采用了Hibernate,所以可以考虑hibernate自带的连接池机制,但是发现效率不高,而且Hibernate也推荐使用c3p0或Proxool连接池,在我们的项目中采用了Proxool

    Proxool-0.9.1

    1.解决不能Unregister jdbc driver的内存泄露问题。 十二月 02, 2013 8:19:43 上午 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc SEVERE: The web application [/xxx] registered the JDBC ...

    proxool_0.9.1

    标题“proxool_0.9.1”提及的是一个名为Proxool的数据库连接池管理工具的特定版本,即0.9.1。Proxool是Apache软件基金会的一个开源项目,它提供了一种轻量级的数据库连接池解决方案,允许开发者更有效地管理和控制...

    proxool相关jar包.rar

    总结来说,"proxool相关jar包.rar"提供的是一组用于管理数据库连接的Java类库,包括Proxool的两个不同版本和其依赖的CGLIB库。这些资源可以帮助开发者构建高效、可监控的数据库连接池,提升Java应用的性能和稳定性。

    proxool 数据库

    **Proxool数据库连接池详解** 在IT行业中,数据库管理是关键的一环,尤其是在高并发、大数据量的应用场景下,数据库连接池的使用显得尤为重要。Proxool是Apache的一个开源项目,它提供了一个轻量级的数据库连接池...

    proxool配置

    这样不仅减少了数据库连接的创建和销毁开销,还能防止过多连接导致的资源耗尽问题。 **配置Proxool** 1. **添加依赖**: 首先,你需要在项目中引入Proxool的库。如果你使用的是Maven,可以在pom.xml文件中添加以下...

    proxool连接池

    **Proxool 连接池详解** Proxool 是一个高效、易用的数据库连接池,它通过提供中间代理层管理数据库连接,从而实现数据库连接的复用,提高应用程序的性能和效率。Proxool 的设计目标是为 Java 应用程序提供简单、...

    proxool链接池

    **Proxool连接池详解** Proxool是Apache软件基金会的一个开源项目,它是一个轻量级的数据库连接池实现,提供了高效、灵活的数据库连接管理。在Java应用程序中,使用数据库连接池可以显著提高数据库操作的性能,因为...

    Proxool api chm

    Java connection pool : Proxool api(chm)

    proxool-0.9.0RC3.jar

    "proxool-0.9.0RC3.jar" 是一个Java档案文件,它包含了Proxool库的0.9.0RC3版本。Proxool是开源的Java连接池实现,设计用于提供数据库连接管理服务,它使得在多线程环境中高效地管理和重用数据库连接成为可能。连接...

    proxool-0.9.1 jar;proxool-cglib.jar;

    压缩包子文件的文件名称列表只提到了"proxool",这可能意味着除了这两个JAR文件外,可能还需要其他依赖库或配置文件才能完整运行Proxool。 总结来说,Proxool是一个功能强大且易于使用的Java数据连接池实现,通过...

    proxool.jar

    **Proxool数据库连接池详解** Proxool是源自SourceForge的一个开源项目,它是一款针对Java平台设计的高效、易用的数据库连接池技术。在Java应用开发中,数据库连接池是一个至关重要的组件,用于管理和复用数据库...

    java连接池proxool

    Java连接池,特别是Proxool,是数据库管理中一个至关重要的概念,它提高了数据库操作的效率和性能。连接池在Java应用程序中起着桥梁的作用,它管理数据库连接,避免了频繁创建和销毁连接的开销。Proxool是Apache软件...

Global site tag (gtag.js) - Google Analytics