求各位朋友帮忙指点

shanzhaikaifa 2014-06-19 11:09:02
小弟有个web程序 使用tomcat发布 jvm最大内存分配了1G, 使用visualvm观察其内存使用发现了如下情况:
1、tomcat启动后 内存占用呈比较平稳的波浪曲线 300-500M之间波动,此时强制回收,内存会降至200;
2、大约两天后占用的内存有所提高 500-800之间波动;
3、在观察三天,发现内存大概在800-顶峰1G之间波动 当接近1G时jvm存在明显的内存回收,但是回收后,内存仍然会占用在800M左右 然后继续上升 然后接近1G时 又产生明显的回收 至800 如此循环
此时的情况会不会出现内存溢出呢?在夜晚 基本无人访问的时候为什么仍然占用了这么多的内存且回收幅度很小呢?
请各位大神指教 非常感谢
...全文
555 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
zx19291588 2014-06-29
  • 打赏
  • 举报
回复
你的问题就是一个虚拟机内存配置的问题,一般我们都是配置在512~256之间,不需要配置1G ,因为程序跑起来,本身就需要一定的内存,所以你把1G改成512就OK了
shanzhaikaifa 2014-06-26
  • 打赏
  • 举报
回复
内存溢出的原因基本找到了,这里和大家分享下我发现问题的分析过程,希望对大家有所用: 1、使用mat观察定期观察heap dump快照,发现birt报表和flex的消息队列占用了很大内存; 2、通过分析和试验证明flex blazeds消息队列始终缓存数据的原因为 用户刷新了浏览器或后退造成了订阅线程无法捕获到退订事件,从而订阅线程不断往queue中写入消息而客户端刷新后停止了轮询,queue中不断堆积消息导致内存溢出,此种情况绝对是偶发的,如果不定时观察分析快照,很难发现,原因为: a、我的系统设计问题 待完善且实施人员未培训用户使用指定的系统首页(弹出窗口打开应用,无刷新和后退按钮,但避免不了F5刷新,只是一种无法彻底解决问题而缓解避免问题的方式);b、flex blazeds对浏览器刷新和后退暂无很好的解决方案和处理机制; 3、基于2的原因我做了如下工作: a、定时gc,回收birt查询后堆积的内存,确保回收及时(这里仅是保障的方式,其实不强制回收也会安全,毕竟jvm会根据自身回收算法回收); b、改写flex blazeds的processor,对过期消息和客户端超时情况进行捕获和处理,确保无法捕获到关闭事件的客户端订阅线程在2分钟内被程序杀死并清理消息队列,防止无限堆积消息,经测试,暂无问题可以达到预期效果; 继续观察2周,如果系统使用稳定,说明以上过程是正确的,问题就解决了,到时结贴发分,谢谢各位的回复,欢迎继续讨论! ps:一年前预料的系统问题采用了回避方式尽量绕行而没有着手彻底从机制上处理,一年后的今天问题终于出现了,我只想说出来混迟早要还的!
疯癫行者 2014-06-20
  • 打赏
  • 举报
回复
引用 14 楼 oh_Maxy 的回复:
如果代码没问题,有没有考虑升级tomcat呢?tomcat6.35+jdk1.6.13,这是之前项目用过的配置,也是经历过内存泄露后,升级验证过的配置。 定时GC,好吧,没试过。。
这个有用,收藏了。 定时GC可以试试,但不是根本,根本还是找出泄漏。
oh_Maxy 2014-06-20
  • 打赏
  • 举报
回复
如果代码没问题,有没有考虑升级tomcat呢?tomcat6.35+jdk1.6.13,这是之前项目用过的配置,也是经历过内存泄露后,升级验证过的配置。 定时GC,好吧,没试过。。
shanzhaikaifa 2014-06-20
  • 打赏
  • 举报
回复
引用 11 楼 oh_Maxy 的回复:
[quote=引用 10 楼 shanzhaikaifa 的回复:] [quote=引用 6 楼 oh_Maxy 的回复:] 你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。 另外,你说的 在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。
是的 应该是白天的内存 但是之前内存都很平稳 强制回收后 回收幅度挺大的 感觉这样肯定不会出问题 但是昨天晚上突然回收都不好使 不断上升 且强制回收效果不明显了 明显是非要溢出的节奏。。。。 我的程序中不涉及文件上传 流读写 ,数据库读取都采用的成熟框架 其他系统也一直在用 感觉问题不在这里 1、用户线程问题 我的程序确实启动了用户线程 每天都会有大量的用户线程启动和消亡 经过几天观察 启动和消亡的线程都可以在visualvm和程序中的页面查询到 说明管理过程是一致的 在控制范围内,而且每天都是如此 即使出问题当时也是一致的 2、birt问题 目前观察 每次内存曲线大幅度上升 都伴随birt访问[/quote] 感觉你也分析出来一些原因了,可以针对性看看birt的处理,有没有使用大对象或者超大list、map等集合。看看能否分批处理。 另外,不建议通过工具强制gc。LZ可以试试,不手动GC,看看会不会真的出现内存溢出。[/quote]
引用 11 楼 oh_Maxy 的回复:
[quote=引用 10 楼 shanzhaikaifa 的回复:] [quote=引用 6 楼 oh_Maxy 的回复:] 你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。 另外,你说的 在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。
是的 应该是白天的内存 但是之前内存都很平稳 强制回收后 回收幅度挺大的 感觉这样肯定不会出问题 但是昨天晚上突然回收都不好使 不断上升 且强制回收效果不明显了 明显是非要溢出的节奏。。。。 我的程序中不涉及文件上传 流读写 ,数据库读取都采用的成熟框架 其他系统也一直在用 感觉问题不在这里 1、用户线程问题 我的程序确实启动了用户线程 每天都会有大量的用户线程启动和消亡 经过几天观察 启动和消亡的线程都可以在visualvm和程序中的页面查询到 说明管理过程是一致的 在控制范围内,而且每天都是如此 即使出问题当时也是一致的 2、birt问题 目前观察 每次内存曲线大幅度上升 都伴随birt访问[/quote] 感觉你也分析出来一些原因了,可以针对性看看birt的处理,有没有使用大对象或者超大list、map等集合。看看能否分批处理。 另外,不建议通过工具强制gc。LZ可以试试,不手动GC,看看会不会真的出现内存溢出。[/quote] 不强制gc也会溢出 我捉摸着不行起个定时器 每小时GC一次 至少可以回收birt访问后驻留的内存
tony4geek 2014-06-20
  • 打赏
  • 举报
回复
不知道是不是birt
oh_Maxy 2014-06-20
  • 打赏
  • 举报
回复
引用 10 楼 shanzhaikaifa 的回复:
[quote=引用 6 楼 oh_Maxy 的回复:] 你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。 另外,你说的 在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。
是的 应该是白天的内存 但是之前内存都很平稳 强制回收后 回收幅度挺大的 感觉这样肯定不会出问题 但是昨天晚上突然回收都不好使 不断上升 且强制回收效果不明显了 明显是非要溢出的节奏。。。。 我的程序中不涉及文件上传 流读写 ,数据库读取都采用的成熟框架 其他系统也一直在用 感觉问题不在这里 1、用户线程问题 我的程序确实启动了用户线程 每天都会有大量的用户线程启动和消亡 经过几天观察 启动和消亡的线程都可以在visualvm和程序中的页面查询到 说明管理过程是一致的 在控制范围内,而且每天都是如此 即使出问题当时也是一致的 2、birt问题 目前观察 每次内存曲线大幅度上升 都伴随birt访问[/quote] 感觉你也分析出来一些原因了,可以针对性看看birt的处理,有没有使用大对象或者超大list、map等集合。看看能否分批处理。 另外,不建议通过工具强制gc。LZ可以试试,不手动GC,看看会不会真的出现内存溢出。
shanzhaikaifa 2014-06-20
  • 打赏
  • 举报
回复
引用 6 楼 oh_Maxy 的回复:
你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。 另外,你说的 在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。
是的 应该是白天的内存 但是之前内存都很平稳 强制回收后 回收幅度挺大的 感觉这样肯定不会出问题 但是昨天晚上突然回收都不好使 不断上升 且强制回收效果不明显了 明显是非要溢出的节奏。。。。 我的程序中不涉及文件上传 流读写 ,数据库读取都采用的成熟框架 其他系统也一直在用 感觉问题不在这里 1、用户线程问题 我的程序确实启动了用户线程 每天都会有大量的用户线程启动和消亡 经过几天观察 启动和消亡的线程都可以在visualvm和程序中的页面查询到 说明管理过程是一致的 在控制范围内,而且每天都是如此 即使出问题当时也是一致的 2、birt问题 目前观察 每次内存曲线大幅度上升 都伴随birt访问
姜小白- 2014-06-20
  • 打赏
  • 举报
回复
引用 7 楼 shanzhaikaifa 的回复:
我现在初步怀疑是birt报表导致的 每次birt访问都伴随曲线的大幅度上升 每次内存曲线明显的上升都伴随着birt访问 通过log日志也可以找到对应时间点的birt日志。。。。但是是初步诊断 也没有充分的证据 还有一个现象是 之前内存强制回收幅度是很大的 但是昨天晚上竟然强制回收后还会快速涨到最大内存数
楼主有怀疑点,那就查看下birt报表访问部分的代码,看看数据读写有没有及时关闭,顺带查下其他的涉及文件读写的代码。 这种问题一般都不是很好跟,之前其他项目组一个问题,流没有关闭,项目上线两周之后服务器给挂了,报内存溢出,但抛出异常的地方早已不是之前内存泄漏的地方了,好几个人排查将近一天,才找到是之前的一个流没有关闭导致的。
shanzhaikaifa 2014-06-20
  • 打赏
  • 举报
回复
引用 6 楼 oh_Maxy 的回复:
你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。 另外,你说的 在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。
回版主 我的版本是tomcat5.5 和 jdk6 运行环境是64位windows2008服务器
shanzhaikaifa 2014-06-20
  • 打赏
  • 举报
回复
引用 5 楼 magi1201 的回复:
[quote=引用 4 楼 shanzhaikaifa 的回复:] 请问如何查找到是什么位置出现了内存泄漏呢 我使用visualvm的thread dump发现 char[]占用最高 但是这个无法定位泄露的位置 找不到原因 对于用户线程确实使用了 但是观察没有发现问题 正常打开后正常死掉 且缓存启动线程的hashtable中缓存的线程也都和visualvm中alive线程一致,说明启动和杀死过程都在程序管理的范围内进行,如果管理不当 应该不会能够正常运行5天的情况,会较早的就内存溢出,所以和迷茫 ,今早发现已经内存溢出了 ,正常运行了1周的时间
按3楼说的方式一点点的查代码,代码中的内存泄露不是很严重,就泄露一点点,但时间长了就会威胁到系统的正常运行。 这也是为什么很多代码自己测试时不出问题,但到正式服务器上面运行一段时间久出现内存泄露的现象,因为家里测试不会那么长时间的让系统一直运行。如何查找到是什么位置出现了内存泄漏,这个比价难,如果系统出现了泄露的异常信息可以帮助查看。一般的就要靠自己分析代码了,重点查看网络连接,数据库读写,文件流读写这几处操作,看操作完是否进行了连接关闭,流关闭。[/quote] 我现在初步怀疑是birt报表导致的 每次birt访问都伴随曲线的大幅度上升 每次内存曲线明显的上升都伴随着birt访问 通过log日志也可以找到对应时间点的birt日志。。。。但是是初步诊断 也没有充分的证据 还有一个现象是 之前内存强制回收幅度是很大的 但是昨天晚上竟然强制回收后还会快速涨到最大内存数
oh_Maxy 2014-06-20
  • 打赏
  • 举报
回复
你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。 另外,你说的 在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。
姜小白- 2014-06-20
  • 打赏
  • 举报
回复
引用 4 楼 shanzhaikaifa 的回复:
请问如何查找到是什么位置出现了内存泄漏呢 我使用visualvm的thread dump发现 char[]占用最高 但是这个无法定位泄露的位置 找不到原因 对于用户线程确实使用了 但是观察没有发现问题 正常打开后正常死掉 且缓存启动线程的hashtable中缓存的线程也都和visualvm中alive线程一致,说明启动和杀死过程都在程序管理的范围内进行,如果管理不当 应该不会能够正常运行5天的情况,会较早的就内存溢出,所以和迷茫 ,今早发现已经内存溢出了 ,正常运行了1周的时间
按3楼说的方式一点点的查代码,代码中的内存泄露不是很严重,就泄露一点点,但时间长了就会威胁到系统的正常运行。 这也是为什么很多代码自己测试时不出问题,但到正式服务器上面运行一段时间久出现内存泄露的现象,因为家里测试不会那么长时间的让系统一直运行。如何查找到是什么位置出现了内存泄漏,这个比价难,如果系统出现了泄露的异常信息可以帮助查看。一般的就要靠自己分析代码了,重点查看网络连接,数据库读写,文件流读写这几处操作,看操作完是否进行了连接关闭,流关闭。
shanzhaikaifa 2014-06-20
  • 打赏
  • 举报
回复
请问如何查找到是什么位置出现了内存泄漏呢 我使用visualvm的thread dump发现 char[]占用最高 但是这个无法定位泄露的位置 找不到原因 对于用户线程确实使用了 但是观察没有发现问题 正常打开后正常死掉 且缓存启动线程的hashtable中缓存的线程也都和visualvm中alive线程一致,说明启动和杀死过程都在程序管理的范围内进行,如果管理不当 应该不会能够正常运行5天的情况,会较早的就内存溢出,所以和迷茫 ,今早发现已经内存溢出了 ,正常运行了1周的时间
oh_Maxy 2014-06-20
  • 打赏
  • 举报
回复
引用 16 楼 shanzhaikaifa 的回复:
[quote=引用 14 楼 oh_Maxy 的回复:] 如果代码没问题,有没有考虑升级tomcat呢?tomcat6.35+jdk1.6.13,这是之前项目用过的配置,也是经历过内存泄露后,升级验证过的配置。 定时GC,好吧,没试过。。
好的 这个配置我记下了 谢谢版主大人指点[/quote] 呃,恰好接触过,别大人小人的啦,心虚啊~
shanzhaikaifa 2014-06-20
  • 打赏
  • 举报
回复
引用 14 楼 oh_Maxy 的回复:
如果代码没问题,有没有考虑升级tomcat呢?tomcat6.35+jdk1.6.13,这是之前项目用过的配置,也是经历过内存泄露后,升级验证过的配置。 定时GC,好吧,没试过。。
好的 这个配置我记下了 谢谢版主大人指点
vnvlyp 2014-06-19
  • 打赏
  • 举报
回复
内存泄露请检查会经常新创建的对象 各种连接、流,比如网络连接,数据库连接,文件流,用完是否close,是否做好收尾工作,是否断开了一切对其的引用(典型的例子就是一个Map存储每个用户的连接和资源等,但用户走了忘记remove) 还有多线程时,每个线程完成任务后是否都能够正常停止,正常被销毁,是否在线程中存在死循环 另外注意像Timer这类会开启另外的线程处理任务的类是否能够停止,并得到释放
疯癫行者 2014-06-19
  • 打赏
  • 举报
回复
如果泄露的内存太多,导致正常运行的内存不够用,就会溢出。
疯癫行者 2014-06-19
  • 打赏
  • 举报
回复
内存泄漏是肯定的。

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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