论坛首页 Java企业应用论坛

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

浏览 33814 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-12-11  
qingshan 写道
这个问题,先从自己程序找原因,去找其他什么连接池都没用。你把auto commit设置为false,那至少执行一定数量的statement(比如说100个)就应该commit一下。

这只是个测试程序!虽然效率不高,但是只执行一遍的话,程序本身不应该引起内存泄露问题吧?


实际的程序采用appfuse1.9的框架,struts1.2+spring2.5+hibernate3,
牵涉到数据库部分只用了hibernateTemplate和jdbcTemplate

系统到现在运行快一天了,好像两个tomcat的内存都上去了。看样子用dbcp也没用,内存泄露不是连接池的问题了。

有没有可能是线程影响的呢?程序中使用了不少Threadlocal
0 请登录后投票
   发表时间:2008-12-11  
很有可能是THREAD LOCAL引起的,要注意threadlocal的使用要清空。
0 请登录后投票
   发表时间:2008-12-11  
2M statements想一次就commit,想没问题也难啊。修改一下程序再测试吧!
0 请登录后投票
   发表时间:2008-12-11   最后修改:2008-12-11
dreamlakyxy 写道
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,以后多探讨探讨


你测试内存泄漏的方法是对的。首先你要确保你在JProfile里面显示实例数量的那个视图中,设置的过滤条件是对的,会不会恰巧把存在内存泄漏的对象给过滤掉了,导致你没有发现。会不会你设置的过滤条件只是针对连接池的那些类,或者只是针对你自己写的那些代码。而其他的第三方包和JDK的实例没有观察到。如果过滤条件设置的没有问题,那么你使用这种方法没有检查出内存泄漏,那可能就是由于其他原因导致的。你可以观察一下你的程序使用的线程数,不知道你们是在什么操作系统上运行的,如果是solaris的话,用prstat观察一下你的进程,NLWP代表该进程使用的线程数,看看这个值在系统刚启动运行不久时是多少,然后再看看出现内存占用率比较高的时候是多少。如果增长了很多,那么可能是由于这个原因引起的。我们之前遇过一次类似的问题,就是由于线程创建过多导致的。
0 请登录后投票
   发表时间:2008-12-12   最后修改:2008-12-12
dreamlakyxy 写道

StringBuilder sb1=new StringBuilder(sb);
sb1.append(i).append("','userId").append(i).append("','userName").append(i).append("',null,'测试课程").append(i).append("',null)");


插一个题外话:
根本不需要这样用StringBuilder,只要+就好了:
sb + i + "','userId" + i + "','userName" + ....
无论是sun、ibm还是eclipse的编译器,全都会自动生成StringBuilder和append,和手工写的是完全一样的
而+比append清晰多了

StringBuilder的一个适用场合是:用+需要生成中间字符串的时候,用StringBuilder替代:
StringBuilder sb = new StringBuilder();
for (...)
  sb.append(....);
sb.toString();

这样是比:
String s = "";
for (...)
  s += ...;

快的多,因为后面这个代码会生成很多字符串

那种只要有多个+就用StringBuilder替换的方式早就过时了,我们得与时俱进嘛,根据合适情况才替换
0 请登录后投票
   发表时间:2008-12-12  
javaeyebird 写道
dreamlakyxy 写道

StringBuilder sb1=new StringBuilder(sb);
sb1.append(i).append("','userId").append(i).append("','userName").append(i).append("',null,'测试课程").append(i).append("',null)");


插一个题外话:
根本不需要这样用StringBuilder,只要+就好了:
sb + i + "','userId" + i + "','userName" + ....
无论是sun、ibm还是eclipse的编译器,全都会自动生成StringBuilder和append,和手工写的是完全一样的
而+比append清晰多了

StringBuilder的一个适用场合是:用+需要生成中间字符串的时候,用StringBuilder替代:
StringBuilder sb = new StringBuilder();
for (...)
  sb.append(....);
sb.toString();

这样是比:
String s = "";
for (...)
  s += ...;

快的多,因为后面这个代码会生成很多字符串

那种只要有多个+就用StringBuilder替换的方式早就过时了,我们得与时俱进嘛,根据合适情况才替换


呵呵,谢谢谢谢,看样子我的知识库确实有点过时了,:)又多学了一招
0 请登录后投票
   发表时间:2008-12-12  
我的系统中也有内存泄漏的问题,但是现在没时间好好查,不过有一次我用jprofer简单查了一下,发现String这个占用内存很大,你是这样的吗?为什么呢
0 请登录后投票
   发表时间:2008-12-12  
无论是sun、ibm还是eclipse的编译器,全都会自动生成StringBuilder和append,和手工写的是完全一样的

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

我只为这个问题研究过手写StringBuilder的append和+ 在sun的JDK 5.0中生成的字节码 得出来实际上最后生成的直接码两者完全一致。并不是编译器的原因了
0 请登录后投票
   发表时间:2008-12-12  
高手确实蛮多,  内在泄漏 确实是个大问题.
0 请登录后投票
   发表时间:2008-12-12  
LZ别遇到问题就怪人家内存泄露....这太损了...我想应该是你的配置不当造成的!我们一直用proxool
0 请登录后投票
论坛首页 Java企业应用版

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