Java web应用内存溢出

pengble 2008-02-22 09:30:07
我用Java开发的web应用老是出现内存快速增长,最后内存溢出的问题。我用的tomcat5,JDK1.4.2,内存最大设为1498M,有时候也很平稳,但快速增长时,则只增不降,很快就内存溢出了。最近站点登录人数平均一天100人吧,即使几十人也有可能内存溢出。但登录人数多出现这种情况会更频繁。我查阅了很多技术资料,在一些内存开销大的模块都加了System.gc()语句,但都无法解决内存溢出。这次我采用的是四层架构,现将示例代码贴出来,请各位技术高手看看有没有问题。
1、WebUser类是映射web_user表字段的值对象类。
2、DbWebUserImpl实现了数据库表记录进行进行基本的增删改的类。
public class DbWebUserImpl implements DbWebUser{
Connection conn = null;

public Connection getConnection() {
return conn;
}

public void setConnection(Connection connection) {
this.conn=connection;
}

public void updateWebUser(WebUser webUser) throws Exception {
String strSql="update web_user set account=?,passwd=?,nickname=? where user_id=?";
PreparedStatement pstm=null;
try{
pstm=conn.prepareStatement(strSql);
int i=1;
pstm.setString(i++,webUser.getAccount());
pstm.setString(i++,webUser.getPasswd());
pstm.setString(i++,webUser.getNickname());
pstm.setInt(i++,webUser.getUser_id().intValue());
pstm.executeUpdate();
}finally{
if(pstm!=null){
pstm.close();
pstm=null;
}
}
}
}
3、WebUserService是服务层,调用数据访问类的方法,表示层(jsp或action)就直接调用WebUserService类的方法
public class WebUserService extends BaseService{
private DbWebUser dbWebUser=DbFactory.getDbWebUser();

public boolean updateWebUser(WebUser webUser){
Connection conn = null;
try{
conn=DataConnect.getConnection();
dbWebUser.setConnection(conn);
dbWebUser.updateWebUser(webUser);

return true;
}catch(Exception ex){
ex.printStackTrace();
message=ex.getMessage();
return false;
}finally{
try{
if(conn!=null) conn.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
4、表示层(jsp或action)通过调用WebUserService类的updateWebUser方法,来更新web_user表的记录。
例如:
WebUserService webUserService=new WebUserService();
Authorization authorization=(Authorization)session.getAttribute("authorization");

WebUserForm f=(WebUserForm)form;
WebUser webUser=webUserService.getWebUser(authorization.getAccount());
webUser.setNickname(f.getNickname());
boolean bret=webUserService.updateWebUser(webUser);
//webUser=null;
请问各位高手,如果这里不加webUser=null,会不会造成内存泄漏?但我将很多类似的模块都加上了Object=null,仍不能解决内存溢出。

这个问题困惑了我很久,一直无法解决。现在论坛提出,请各位老师帮帮忙,非常感谢!
...全文
4595 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhbwww 2009-11-26
  • 打赏
  • 举报
回复
xuexi
sui366 2009-08-04
  • 打赏
  • 举报
回复
在使用Ajax请求情况下,在控制层List,Map对象一旦清除,将导致页面无法获得数据,那么,在这种情况下是不是对清除集合对象无能为力了呢
qiufei2008 2009-05-22
  • 打赏
  • 举报
回复
不错
bushiliumang 2009-01-15
  • 打赏
  • 举报
回复
你有没有finally啊,释放一下不就好了么?
qiancaoduwu 2008-09-02
  • 打赏
  • 举报
回复
哎 我也遇到了同样的问题,头疼!
ghosert 2008-03-03
  • 打赏
  • 举报
回复
楼主试验过了给个说法,如果不是这个问题,我再帮你继续分析其他原因。
ghosert 2008-03-03
  • 打赏
  • 举报
回复
WebUserService webUserService=new WebUserService();
...
...
//webUser=null;
请问各位高手,如果这里不加webUser=null,会不会造成内存泄漏?但我将很多类似的模块都加上了Object=null,仍不能解决内存溢出。

这个地方,首先因为是方法内的变量所以不加=null也没问题因为方法结束后,虚拟机自动做垃圾回收。
问题在于,你这个WebUserService最好做一个Singleton调用,WEB程序是在多线程环境下调用的,申请一个方法变量的结果是每个线程都会new一个对象
100来人就 new 100多个然后释放,Singletone的话所有线程共用一个实例,减小了不少开销,但注意线程安全问题(多数情况下,没有这种问题)

我的回答不一定会解决你的问题,但是你可以试试。

pengble 2008-03-01
  • 打赏
  • 举报
回复
谢谢guying1028的回答,请问你说的输出日志,是指用log4j输出日志吗?这个很消耗内存吗
前几天试过这种方法:Tomcat设置GC监控:在catalina.bat的“set JAVA_OPTS=%JAVA_OPTS% ”后加“-verbose:gc”;将GC日志输出到文件“-Xloggc:filename”;但却发现看不明白,根本无法了解是哪个具体的对象在消耗内存.
guying1028 2008-02-28
  • 打赏
  • 举报
回复
不仅前公司做的一个项目中,也遇到了内存溢出的问题,我那个问题是在取数据的时候涉及到很多表,一次取出的数据量太大,还要不停的循环,运行环境和楼主的一样。后来没办法也是不停地找问题:把String的叠加改成StringBuffer,日志的输出减少一点,只留下比较重要的日志,还有调试的时候输出的:System.out.println();这样的输出给仔细检查删除掉。最后系统的性能好多了,主要是打印日志太耗内存了。后来又把tomcat的启动内存给加大了很多才彻底解决问题。这只是我在项目中遇到的个人问题,不知道对楼主有没有用啊!
周小白 2008-02-28
  • 打赏
  • 举报
回复
you can try to this ,follow me!

Tool usage:

启动
java -Xmx512M -jar HR205.jar ..\heap\heapdump.20031111.100658.2144.txt
-------------------------------------------------------------------------------
常用命令
ts
tc

gs
gc

p
ot
-------------------------------------------------------------------------------
> p
ot可以分析对象内存使用情况
> ot

Enter name to filter on or '-' for no filtering [-]
>
Enter combination of types to show, R for Roots, A for Artificial Roots, N for N
on-Roots [R,A,N]
>
Enter 0x<addr> of a 'root' to show only objects owned by it or '-' for no filter
ing [-]
>
Enter address range in format 'M','L-U','-U' or 'L-' [0x00000000-0xFFFFFFFF]
>
Enter range of lines to print in format 'M','L-U','-U' or 'L-' [100-200]


Addr Size Root-owner Parent Total-size Name
-------------------------------------------------------------------------------
N 0x094fe170 256 0x0101adc0 0x03e0a078 79,220,456 class com/xxsoft/tp/
core/prservice/monitor/MonitorManager


use i to dig into object
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
XX银行pmr83084.000.672 log 分析

> d

Enter total-size threshold [100000]
>
Enter max depth or -ve for unlimited [20]
>
Enter 0x<addr> to dump from one address or any value for all roots [-]
>
Dumping object(s) : 15942 roots, sorted by total-size
Filter : total-size >= 100,000 and depth at most 20
Prune : N

<0> [759,321,472] 0x1008bfa0 [32] java/util/Hashtable$Entry
<1> [759,321,424] 0x1008bff0 [72] com/xxsoft/upload/File
<2> [759,321,080] 0x25293610 [96] com/xxsoft/upload/xxsoftUpload
<3> [759,229,112] 0x252922c8 [24] com/xxsoft/upload/Files
<4> [759,229,088] 0x25292298 [48] java/util/Hashtable
<5> [759,229,040] 0x241ad268 [6,291,472] array of java/util/Hashtable$Entry
<6> {759,321,472} 0x1008bfa0 [32] java/util/Hashtable$Entry
- 1094386 children of 0x241ad268 filtered.
<3> <17,658,808 root:0x1020e520> 0x1bc2db18 [136] com/ibm/ws/webcontainer/webapp/WebApp
- 8 children of 0x25293610 filtered.
- 9 children of 0x1008bff0 filtered.
- 1 child of 0x1008bfa0 filtered.





-------------------------------------------------------------------------------
> ot

Enter name to filter on or '-' for no filtering [-]
>
Enter combination of types to show, R for Roots, A for Artificial Roots, N for Non-Roots [A,R,N]
>
Enter 0x<addr> of a 'root' to show only objects owned by it or '-' for no filtering [-]
>
Enter address range in format 'M','L-U','-U' or 'L-' [0x00000000-0xFFFFFFFF]
>
Enter range of lines to print in format 'M','L-U','-U' or 'L-' [1-5]
> 1-10
Showing all objects, sorted by total-size.

Addr Size Root-owner Parent Total-size Name
-------------------------------------------------------------------------------
A 0x1008bfa0 32 - - 759,321,472 java/util/Hashtable$Entry
N 0x1008bff0 72 0x1008bfa0 0x1008bfa0 759,321,424 com/xxsoft/upload/File
N 0x25293610 96 0x1008bfa0 0x1008bff0 759,321,080 com/xxsoft/upload/xxsoftUpload
N 0x252922c8 24 0x1008bfa0 0x25293610 759,229,112 com/xxsoft/upload/Files
N 0x25292298 48 0x1008bfa0 0x252922c8 759,229,088 java/util/Hashtable
N 0x241ad268 6,291,472 0x1008bfa0 0x25292298 759,229,040 array of java/util/Hashtable$Entry
R 0x1020e520 32 - - 26,711,160 com/ibm/ejs/util/am/_Alarm

-------------------------------------------------------------------------------
Primetoy 分析
> ot

Enter name to filter on or '-' for no filtering [-]
>
Enter combination of types to show, R for Roots, A for Artificial Roots, N for N
on-Roots [A,R,N]
>
Enter 0x<addr> of a 'root' to show only objects owned by it or '-' for no filter
ing [-]
>
Enter address range in format 'M','L-U','-U' or 'L-' [0x00000000-0xFFFFFFFF]
>
Enter range of lines to print in format 'M','L-U','-U' or 'L-' [1-200]
>

Showing all objects, sorted by total-size.

Addr Size Root-owner Parent Total-size Name
-------------------------------------------------------------------------------
R 0x0101adc0 32 - - 171,443,056 com/ibm/ejs/util/am/_Alarm
N 0x0b5d23a0 168 0x0101adc0 0x0101adc0 171,443,024 com/ibm/ejs/util/cache/SweepLruEvictionStrategy
.............
N 0x094fe170 256 0x0101adc0 0x03e0a078 79,220,456 class com/xxsoft/tp/core/prservice/monitor/MonitorManager
N 0x092f8738 24 0x0101adc0 0x094fe170 79,220,200 com/xxsoft/tp/core/prservice/monitor/MonitorManager
N 0x09200e08 56 0x0101adc0 0x092f8738 79,220,176 java/util/HashMap
N 0x050a3180 24,592 0x0101adc0 0x09200e08 79,220,120 array of java/util/HashMap$Entry



-------------------------------------------------------------------------------
> d 0x094fe170

Dumping object(s) : 0x094fe170 (parent 0x03e0a078 root 0x0101adc0), sorted by t
otal-size
Filter : total-size >= 1,048,576 and depth at most 10
Prune : N

<0> [79,220,456] 0x094fe170 [256] class com/xxsoft/tp/core/prservice/monitor/M
onitorManager
<1> [79,220,200] 0x092f8738 [24] com/xxsoft/tp/core/prservice/monitor/Monito
rManager
<2> [79,220,176] 0x09200e08 [56] java/util/HashMap
<3> [79,220,120] 0x050a3180 [24,592] array of java/util/HashMap$Entry
- 2260 children of 0x050a3180 filtered.

There were 4 objects expanded.

















> d > xx.txt

Redirecting command output to file 'xx.txt'.

Enter total-size threshold [1048576]
>
Enter max depth or -ve for unlimited [1000]
>
Enter 0x<addr> to dump from one address or any value for all roots [-]
>

Dumping object(s) : 64493 roots, sorted by total-size
Filter : total-size >= 1,048,576 and depth at most 1000
Prune : N

<0> [171,443,056] 0x0101adc0 [32] com/ibm/ejs/util/am/_Alarm
<1> [171,443,024] 0x0b5d23a0 [168] com/ibm/ejs/util/cache/SweepLruEvictionStrategy
<2> [171,442,360] 0x00913f78 [112] com/ibm/ws/bootstrap/ExtClassLoader
<3> [170,920,512] 0x00b5c5d0 [32] java/util/Vector
<4> [170,920,480] 0x0b03f2b0 [40,976] array of java/lang/Object
<5> [165,744,624] 0x02bf7608 [256] class com/ibm/ejs/cm/DSFactoryImpl
<6> [165,744,224] 0x028550d0 [48] java/util/Hashtable
<7> [165,744,176] 0x02852488 [64] array of java/util/Hashtable$Entry
<8> [165,744,112] 0x02a37440 [32] java/util/Hashtable$Entry
<9> [165,744,000] 0x02a3df10 [24] com/ibm/ejs/cm/JDBC1PhaseRF
<10> [159,499,520] 0x0282b168 [32] com/ibm/ws/management/collaborator/DefaultRuntimeCollaborator
<11> [159,499,488] 0x024e6ad8 [24] javax/management/modelmbean/RequiredModelMBean
<12> [159,499,440] 0x02505ef8 [24] com/tivoli/jmx/modelmbean/MMBNotificationBroadcasterSupport
<13> [159,498,968] 0x025010b8 [24] com/tivoli/jmx/modelmbean/MMBNotificationBroadcaster
<14> [159,497,424] 0x02977338 [16] javax/management/NotificationBroadcasterSupport
<15> [159,497,408] 0x0297b810 [16] java/util/HashSet
<16> [159,497,392] 0x024db370 [56] java/util/HashMap
<17> [159,497,320] 0x02500de0 [64] array of java/util/HashMap$Entry
<18> [159,497,256] 0x029e4c98 [32] java/util/HashMap$Entry
<19> [159,497,224] 0x029d8ef0
fastunit 2008-02-25
  • 打赏
  • 举报
回复
内存问题一般来说是由于程序不当引起的。
按你的描述来看,应该和登录人数没有直接关系,虽然人数多会增加问题出现的频率。
最重要的是尽可能重现故障,找出引起内存据高不下的规律来确定问题的起因,比如,执行某个功能后内存急剧上升。
我的一次经历是由于String的累加引起的,改为StringBuffer就解决了,但找到这个原因花费了很多天时间。
引起内存问题的补充:大量的String累加;SQL优化及避免频繁取出大量数据;Session中不要放大的数据。。。

分析手段:
1。Tomcat设置GC监控:在catalina.bat的“set JAVA_OPTS=%JAVA_OPTS% ”后加“-verbose:gc”;将GC日志输出到文件“-Xloggc:filename”;图形分析工具有HP的jtune
2。监控JVM内存、分析日志、程序中设置监控断点:看在出现问题前发生了哪些操作
3。检查关键程序或频繁使用的工具类的合理性

临时应急措施:
1. 程序中判断内存吃紧时执行Runtime.gc()强制垃圾收集,可一定程度上改善内存利用效率,但不能解决根本问题
2. 在不影响业务的情况下,定期重启应用服务器
老紫竹 2008-02-25
  • 打赏
  • 举报
回复
为何没看到你使用jmap之类的工具,把内存占用情况发上来。

表 3. 故障排除工具
工具 说明
jinfo 配置信息
jhat 堆转储浏览器
jmap 内存映射
jsadebugd 服务能力代理调试程序
jstack 堆栈跟踪

jinfo 命令行工具从运行中的 Java 进程或崩溃转储(crash dump)中获取配置信息,并对系统属性和用于启动虚拟机的标记进行打印。

jhat 工具提供了一种方便的方法,可以在堆快照中浏览对象结构。Java SE 6 版本中引入的这个工具可以取代 Heap Analysis Tool (HAT),有助于检测内存泄漏。

jmap 命令行工具为运行中的 VM 或核心文件打印与内存有关的统计信息。该工具还可以使用 jsadebugd 守护程序查询远程机器中的进程或核心文件。jmap 工具可检测出是否过度使用了完成器,后者可导致出现 OutOfMemoryError 错误。

Serviceability Agent Debug Daemon (jsadebugd) 连接到一个 Java 进程或一个核心文件,并充当一个调试服务器。该工具当前只能用于 Solaris OS 和 Linux®。诸如 jstack、jmap 和 jinfo 这样的远程客户机可以通过 Java RMI 连接到这种服务器上。

jstack 命令行工具连接到指定的进程或核心文件,并打印所有连接到虚拟机的线程的堆栈跟踪信息,包括 Java 线程和 VM 内部线程,有时也包括本地堆栈框架。该工具还执行死锁检测。它使用 jsadebugd 守护程序查询远程机器上的进程或核心文件。jstack 工具可用于检测死锁问题。
老紫竹 2008-02-24
  • 打赏
  • 举报
回复
http://www.java2000.net/viewthread.jsp?tid=1377
我也是猜测,因为我只遇到过这几种情况。

static Set/List/Map 的可能性最高。
singleton的 Set/List/Map 也有这个问题
session 同样
pengble 2008-02-24
  • 打赏
  • 举报
回复
谢谢楼上几位的回复!
但对楼上所述不太明白:“你把某个对象放到了一个Set/List/Map 里面,用完了有忘了释放 ”
请问应该怎样才算释放?
我在jsp迭代集合的代码如下:
<% List list=(List)request.getAttribute("list");
WebUser bean=null;
for(int i=0;i<list.size();i++){
bean=(WebUser)list.get(i); %>
<tr><td><%=bean.getAccount()%></td></tr>
<% } %>
这样写可能吧?还要怎样释放呢?

另外我在某个JSP页面用了
<%! Map map=new HashMap(); %>
但我在页面结尾处写了
<% map.clear(); %>
这样还不行吗?
pengble 2008-02-24
  • 打赏
  • 举报
回复
1、您是指static或singleton的List/Map/Set才需要remove,是吧?普通的临时的List/Map/Set对象是不需要remove的,是吧?
2、有一个Jsp用了<%! Map map=new HashMap(); %> ,是出于程序功能实现的考虑。但这个不是问题,因为我把这段屏蔽掉,还是照样会内存溢出。
3、session应该没问题,因为只保存了很简单的用户登录权限
4、我没把图片存在内存里
谢谢!
老紫竹 2008-02-24
  • 打赏
  • 举报
回复
我能想到的内存溢出的原因
1 递归循环了
2 你把某个对象放到了一个Set/List/Map 里面,用完了有忘了释放
在你的static 的对象/ 单例类也算
里面找吧,所有涉及到set/list/map的都差一遍

3 你把某些集合放到了 session/application 里面了,
这样,如果session不过期,他们占用内存就不会释放,即使其他地方被null也没用

你可以打开jconsole 动态监控一下内存情况,看看是哪个内存类型溢出了。
楼上几位的查看方法同样重要。我曾见一个溢出是因为整型对象竟然占用了800M的内存,呵呵。
老紫竹 2008-02-24
  • 打赏
  • 举报
回复
第一就是尽量不用
第二.clear()是可以的,不过既然可以clear, 就可以考虑使用临时变量代替,而不是静态变量和类一级的变量。
第三,session只保存最基本类型,或者自定义的简单的POJO

具体的,你逐个全文搜索 List/Map/Set 看看
每个地方逐个检查, 有add和put, 但没有remove的都要注意。

第四,我那个里面已经说了,你是不是把附件/图片什么的也放到内存了?
pengble 2008-02-24
  • 打赏
  • 举报
回复
非常感谢老紫竹,但帮人帮到底,请您说具体点.
Set/List/Map 的可能性最高。还有递归循环。应该怎样释放内存,能把您遇到过的情况代码贴出来吗?
好不容易碰到一个明白人,请您把具体的代码贴出来讲一下,可以吗?感激不尽!
yill 2008-02-24
  • 打赏
  • 举报
回复
另外 System.gc() 没有用的
yill 2008-02-24
  • 打赏
  • 举报
回复
一般内存泄露的原因都会在线程操作、数据库或者文件等操作上面 。

要定位的话可以借助工具,比如你说的 jprofile 或者 optimize,不过工具对原有系统的影响是很大的。

这种情况下,可以打开java 的 gc 参数,关注堆内存是否有持续增加。

程序运行过程中可以打 java 进程的堆栈信息分析线程 情况,看是否有线程等待、死锁等情况。

另外,内存溢出一般会有异常堆栈或者core文件吧,这个也要好好分析一下。
加载更多回复(5)

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧