求各位朋友帮忙指点

问题描述

小弟有个web程序使用tomcat发布jvm最大内存分配了1G,使用visualvm观察其内存使用发现了如下情况:1、tomcat启动后内存占用呈比较平稳的波浪曲线300-500M之间波动,此时强制回收,内存会降至200;2、大约两天后占用的内存有所提高500-800之间波动;3、在观察三天,发现内存大概在800-顶峰1G之间波动当接近1G时jvm存在明显的内存回收,但是回收后,内存仍然会占用在800M左右然后继续上升然后接近1G时又产生明显的回收至800如此循环此时的情况会不会出现内存溢出呢?在夜晚基本无人访问的时候为什么仍然占用了这么多的内存且回收幅度很小呢?请各位大神指教非常感谢

解决方案

解决方案二:
内存泄漏是肯定的。
解决方案三:
如果泄露的内存太多,导致正常运行的内存不够用,就会溢出。
解决方案四:
内存泄露请检查会经常新创建的对象各种连接、流,比如网络连接,数据库连接,文件流,用完是否close,是否做好收尾工作,是否断开了一切对其的引用(典型的例子就是一个Map存储每个用户的连接和资源等,但用户走了忘记remove)还有多线程时,每个线程完成任务后是否都能够正常停止,正常被销毁,是否在线程中存在死循环另外注意像Timer这类会开启另外的线程处理任务的类是否能够停止,并得到释放
解决方案五:
请问如何查找到是什么位置出现了内存泄漏呢我使用visualvm的threaddump发现char[]占用最高但是这个无法定位泄露的位置找不到原因对于用户线程确实使用了但是观察没有发现问题正常打开后正常死掉且缓存启动线程的hashtable中缓存的线程也都和visualvm中alive线程一致,说明启动和杀死过程都在程序管理的范围内进行,如果管理不当应该不会能够正常运行5天的情况,会较早的就内存溢出,所以和迷茫,今早发现已经内存溢出了,正常运行了1周的时间
解决方案六:
引用4楼shanzhaikaifa的回复:

请问如何查找到是什么位置出现了内存泄漏呢我使用visualvm的threaddump发现char[]占用最高但是这个无法定位泄露的位置找不到原因对于用户线程确实使用了但是观察没有发现问题正常打开后正常死掉且缓存启动线程的hashtable中缓存的线程也都和visualvm中alive线程一致,说明启动和杀死过程都在程序管理的范围内进行,如果管理不当应该不会能够正常运行5天的情况,会较早的就内存溢出,所以和迷茫,今早发现已经内存溢出了,正常运行了1周的时间

按3楼说的方式一点点的查代码,代码中的内存泄露不是很严重,就泄露一点点,但时间长了就会威胁到系统的正常运行。这也是为什么很多代码自己测试时不出问题,但到正式服务器上面运行一段时间久出现内存泄露的现象,因为家里测试不会那么长时间的让系统一直运行。如何查找到是什么位置出现了内存泄漏,这个比价难,如果系统出现了泄露的异常信息可以帮助查看。一般的就要靠自己分析代码了,重点查看网络连接,数据库读写,文件流读写这几处操作,看操作完是否进行了连接关闭,流关闭。
解决方案七:
你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。另外,你说的在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。
解决方案八:
引用5楼magi1201的回复:

Quote: 引用4楼shanzhaikaifa的回复:
请问如何查找到是什么位置出现了内存泄漏呢我使用visualvm的threaddump发现char[]占用最高但是这个无法定位泄露的位置找不到原因对于用户线程确实使用了但是观察没有发现问题正常打开后正常死掉且缓存启动线程的hashtable中缓存的线程也都和visualvm中alive线程一致,说明启动和杀死过程都在程序管理的范围内进行,如果管理不当应该不会能够正常运行5天的情况,会较早的就内存溢出,所以和迷茫,今早发现已经内存溢出了,正常运行了1周的时间

按3楼说的方式一点点的查代码,代码中的内存泄露不是很严重,就泄露一点点,但时间长了就会威胁到系统的正常运行。这也是为什么很多代码自己测试时不出问题,但到正式服务器上面运行一段时间久出现内存泄露的现象,因为家里测试不会那么长时间的让系统一直运行。如何查找到是什么位置出现了内存泄漏,这个比价难,如果系统出现了泄露的异常信息可以帮助查看。一般的就要靠自己分析代码了,重点查看网络连接,数据库读写,文件流读写这几处操作,看操作完是否进行了连接关闭,流关闭。

我现在初步怀疑是birt报表导致的每次birt访问都伴随曲线的大幅度上升每次内存曲线明显的上升都伴随着birt访问通过log日志也可以找到对应时间点的birt日志。。。。但是是初步诊断也没有充分的证据还有一个现象是之前内存强制回收幅度是很大的但是昨天晚上竟然强制回收后还会快速涨到最大内存数
解决方案九:
引用6楼oh_Maxy的回复:

你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。另外,你说的在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。

回版主我的版本是tomcat5.5和jdk6运行环境是64位windows2008服务器
解决方案十:
引用7楼shanzhaikaifa的回复:

我现在初步怀疑是birt报表导致的每次birt访问都伴随曲线的大幅度上升每次内存曲线明显的上升都伴随着birt访问通过log日志也可以找到对应时间点的birt日志。。。。但是是初步诊断也没有充分的证据还有一个现象是之前内存强制回收幅度是很大的但是昨天晚上竟然强制回收后还会快速涨到最大内存数

楼主有怀疑点,那就查看下birt报表访问部分的代码,看看数据读写有没有及时关闭,顺带查下其他的涉及文件读写的代码。这种问题一般都不是很好跟,之前其他项目组一个问题,流没有关闭,项目上线两周之后服务器给挂了,报内存溢出,但抛出异常的地方早已不是之前内存泄漏的地方了,好几个人排查将近一天,才找到是之前的一个流没有关闭导致的。
解决方案十一:
引用6楼oh_Maxy的回复:

你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。另外,你说的在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。

是的应该是白天的内存但是之前内存都很平稳强制回收后回收幅度挺大的感觉这样肯定不会出问题但是昨天晚上突然回收都不好使不断上升且强制回收效果不明显了明显是非要溢出的节奏。。。。我的程序中不涉及文件上传流读写,数据库读取都采用的成熟框架其他系统也一直在用感觉问题不在这里1、用户线程问题我的程序确实启动了用户线程每天都会有大量的用户线程启动和消亡经过几天观察启动和消亡的线程都可以在visualvm和程序中的页面查询到说明管理过程是一致的在控制范围内,而且每天都是如此即使出问题当时也是一致的2、birt问题目前观察每次内存曲线大幅度上升都伴随birt访问
解决方案十二:
引用10楼shanzhaikaifa的回复:

Quote: 引用6楼oh_Maxy的回复:
你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。另外,你说的在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。

是的应该是白天的内存但是之前内存都很平稳强制回收后回收幅度挺大的感觉这样肯定不会出问题但是昨天晚上突然回收都不好使不断上升且强制回收效果不明显了明显是非要溢出的节奏。。。。我的程序中不涉及文件上传流读写,数据库读取都采用的成熟框架其他系统也一直在用感觉问题不在这里1、用户线程问题我的程序确实启动了用户线程每天都会有大量的用户线程启动和消亡经过几天观察启动和消亡的线程都可以在visualvm和程序中的页面查询到说明管理过程是一致的在控制范围内,而且每天都是如此即使出问题当时也是一致的2、birt问题目前观察每次内存曲线大幅度上升都伴随birt访问

感觉你也分析出来一些原因了,可以针对性看看birt的处理,有没有使用大对象或者超大list、map等集合。看看能否分批处理。另外,不建议通过工具强制gc。LZ可以试试,不手动GC,看看会不会真的出现内存溢出。
解决方案十三:
不知道是不是birt
解决方案十四:
引用11楼oh_Maxy的回复:

Quote: 引用10楼shanzhaikaifa的回复:
Quote: 引用6楼oh_Maxy的回复:
你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。另外,你说的在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。

是的应该是白天的内存但是之前内存都很平稳强制回收后回收幅度挺大的感觉这样肯定不会出问题但是昨天晚上突然回收都不好使不断上升且强制回收效果不明显了明显是非要溢出的节奏。。。。我的程序中不涉及文件上传流读写,数据库读取都采用的成熟框架其他系统也一直在用感觉问题不在这里1、用户线程问题我的程序确实启动了用户线程每天都会有大量的用户线程启动和消亡经过几天观察启动和消亡的线程都可以在visualvm和程序中的页面查询到说明管理过程是一致的在控制范围内,而且每天都是如此即使出问题当时也是一致的2、birt问题目前观察每次内存曲线大幅度上升都伴随birt访问

感觉你也分析出来一些原因了,可以针对性看看birt的处理,有没有使用大对象或者超大list、map等集合。看看能否分批处理。另外,不建议通过工具强制gc。LZ可以试试,不手动GC,看看会不会真的出现内存溢出。

引用11楼oh_Maxy的回复:

Quote: 引用10楼shanzhaikaifa的回复:
Quote: 引用6楼oh_Maxy的回复:
你的tomcat和jdk版本是什么?好像tomcat6.x和jdk5配合,存在内存泄露。另外,你说的在夜晚内存还是占用很多,这个只能说明白天用的内存没有立即回收。垃圾回收不是说用完了就立即会回收的。

是的应该是白天的内存但是之前内存都很平稳强制回收后回收幅度挺大的感觉这样肯定不会出问题但是昨天晚上突然回收都不好使不断上升且强制回收效果不明显了明显是非要溢出的节奏。。。。我的程序中不涉及文件上传流读写,数据库读取都采用的成熟框架其他系统也一直在用感觉问题不在这里1、用户线程问题我的程序确实启动了用户线程每天都会有大量的用户线程启动和消亡经过几天观察启动和消亡的线程都可以在visualvm和程序中的页面查询到说明管理过程是一致的在控制范围内,而且每天都是如此即使出问题当时也是一致的2、birt问题目前观察每次内存曲线大幅度上升都伴随birt访问

感觉你也分析出来一些原因了,可以针对性看看birt的处理,有没有使用大对象或者超大list、map等集合。看看能否分批处理。另外,不建议通过工具强制gc。LZ可以试试,不手动GC,看看会不会真的出现内存溢出。

不强制gc也会溢出我捉摸着不行起个定时器每小时GC一次至少可以回收birt访问后驻留的内存
解决方案十五:
如果代码没问题,有没有考虑升级tomcat呢?tomcat6.35+jdk1.6.13,这是之前项目用过的配置,也是经历过内存泄露后,升级验证过的配置。定时GC,好吧,没试过。。
解决方案:
引用14楼oh_Maxy的回复:

如果代码没问题,有没有考虑升级tomcat呢?tomcat6.35+jdk1.6.13,这是之前项目用过的配置,也是经历过内存泄露后,升级验证过的配置。定时GC,好吧,没试过。。

这个有用,收藏了。定时GC可以试试,但不是根本,根本还是找出泄漏。
解决方案:
引用14楼oh_Maxy的回复:

如果代码没问题,有没有考虑升级tomcat呢?tomcat6.35+jdk1.6.13,这是之前项目用过的配置,也是经历过内存泄露后,升级验证过的配置。定时GC,好吧,没试过。。

好的这个配置我记下了谢谢版主大人指点
解决方案:
引用16楼shanzhaikaifa的回复:

Quote: 引用14楼oh_Maxy的回复:
如果代码没问题,有没有考虑升级tomcat呢?tomcat6.35+jdk1.6.13,这是之前项目用过的配置,也是经历过内存泄露后,升级验证过的配置。定时GC,好吧,没试过。。

好的这个配置我记下了谢谢版主大人指点

呃,恰好接触过,别大人小人的啦,心虚啊~
解决方案:
内存溢出的原因基本找到了,这里和大家分享下我发现问题的分析过程,希望对大家有所用:1、使用mat观察定期观察heapdump快照,发现birt报表和flex的消息队列占用了很大内存;2、通过分析和试验证明flexblazeds消息队列始终缓存数据的原因为用户刷新了浏览器或后退造成了订阅线程无法捕获到退订事件,从而订阅线程不断往queue中写入消息而客户端刷新后停止了轮询,queue中不断堆积消息导致内存溢出,此种情况绝对是偶发的,如果不定时观察分析快照,很难发现,原因为:a、我的系统设计问题待完善且实施人员未培训用户使用指定的系统首页(弹出窗口打开应用,无刷新和后退按钮,但避免不了F5刷新,只是一种无法彻底解决问题而缓解避免问题的方式);b、flexblazeds对浏览器刷新和后退暂无很好的解决方案和处理机制;3、基于2的原因我做了如下工作:a、定时gc,回收birt查询后堆积的内存,确保回收及时(这里仅是保障的方式,其实不强制回收也会安全,毕竟jvm会根据自身回收算法回收);b、改写flexblazeds的processor,对过期消息和客户端超时情况进行捕获和处理,确保无法捕获到关闭事件的客户端订阅线程在2分钟内被程序杀死并清理消息队列,防止无限堆积消息,经测试,暂无问题可以达到预期效果;继续观察2周,如果系统使用稳定,说明以上过程是正确的,问题就解决了,到时结贴发分,谢谢各位的回复,欢迎继续讨论!ps:一年前预料的系统问题采用了回避方式尽量绕行而没有着手彻底从机制上处理,一年后的今天问题终于出现了,我只想说出来混迟早要还的!
解决方案:
你的问题就是一个虚拟机内存配置的问题,一般我们都是配置在512~256之间,不需要配置1G,因为程序跑起来,本身就需要一定的内存,所以你把1G改成512就OK了

时间: 2024-09-11 00:18:25

求各位朋友帮忙指点的相关文章

unity3D 求大神帮忙指点!!!!!!急急急

问题描述 unity3D 求大神帮忙指点!!!!!!急急急 unity场景里有三个cube 在plan上 选中其中一个后:在plan上点哪里选中的cube 就去那里!! 我不会的地方就是 这个选中的部分 !!!和选中后如何连接寻路那个script的地方!!麻烦大神指点!!!!! 解决方案 先用射线找到点到的那个物体 具体代码 RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physi

android-问个fragment布局加载的问题,纠结了一天了,求大神帮忙指点一下,谢谢了

问题描述 问个fragment布局加载的问题,纠结了一天了,求大神帮忙指点一下,谢谢了 下班回家了,没图,我详细说下吧. 网上找了个图,类似这种,我是这样实现的,左边一个listfragment,右边一个framelayout,当点击左边条目时,往frame中加载fragment,但是三级分类我们是图片配文字的(上图中只有文字),fragment中是listview加载的图片,我用的imageloader,都是从网络请求,耗时相对较长,请求完成后fragment才显示的,那么问题来了,当我快速切

c++刚学 运算符重载 求大神帮忙指点 感激不尽

问题描述 c++刚学 运算符重载 求大神帮忙指点 感激不尽 #ifndef DECIMAL_H #define DECIMAL_H #include using std::ostream; using std::istream; class Decimal { public: friend istream &operator>>( istream &, Decimal & ); friend ostream &operator<<(ostream &

用友软件-求大神帮忙指点修改SQL数据库中所有特定字符串

问题描述 求大神帮忙指点修改SQL数据库中所有特定字符串 俺有一门水课,看着书一步步地照着做一个用友软件的项目,真的很无聊,记录公司发生的各种交易.我现在想把同学的作业拿过来改一下然后上交.这个用友软件用SQL数据库管理数据.这个用友软件,每个项目有一个账套主管,各种交易需要主管在软件里授权签名.现在我想做的是,首先修改账套主管名字,然而由于各个交易的签字信息不会随账套主管名字改变,我还得修改各个交易的签字. 直观的办法是,直接在SQL里搜索所有值为账套主管名字的字符串,然后替换成我的名字,求S

sdk-前前后吼折腾几天个晚上了,求大神帮忙指点!

问题描述 前前后吼折腾几天个晚上了,求大神帮忙指点! This Android SDK requires And...te ADT to the latest version我已经将ADT更新到最新了,还是提示这样,怎么解决啊!! 解决方案 看下你的ADT是什么版本的 解决方案二: 提示的意思是你的android 需要高版本的adt 解决方案三: 如果是这个错误的话,你肯定没有更新到最新版的adt 解决方案四: 这个问题好解决啊,我博客里都写明了,你怎么没百度下??找到sdk目录tool目录下的

android开发-这个搜索功能怎么实现呀?求大神帮忙指点,谢谢!下面是代码

问题描述 这个搜索功能怎么实现呀?求大神帮忙指点,谢谢!下面是代码 主程序的:public class MainActivity extends Activity { private ListView listview; private MedicineService medicineservice; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVi

控件呈现错误,求大神帮忙指点一下,万分感谢!

问题描述 在aspx页面拖入了一个GridView控件切换到设计界面报错其他数据控件都没问题,求大神指点下什么原因,万分感谢! 解决方案 解决方案二:添加System.ComponentModel.DataAnnotations.dll的引用解决方案三:1.类型"GridView"的控件必须放在具有runat=server的窗体标记内.2.在后台文件中直接加入重载VerifyRenderingInServerForm方法,如:publicoverridevoidVerifyRender

c# 基础知识-已知:0.37*X+1.14*Y=95927.6, X和Y是整数。求解:X=? Y=? 求大神帮忙

问题描述 已知:0.37*X+1.14*Y=95927.6, X和Y是整数.求解:X=? Y=? 求大神帮忙 本人新手一枚,用的是C#,就是得不出结果,求大神帮忙指点一下! using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace _1 { class Program { static void Main(string[] args) { for (int x =

ie 9-IE9及以上浏览器跨域信息传递失败,求帮忙指点

问题描述 IE9及以上浏览器跨域信息传递失败,求帮忙指点 我想在页面上做跨域消息传递,于是用了以下方法,可是在IE9及以上浏览器测试失败,请问各位有没有什么好的解决方法供小弟用以下,感激不尽. if(window.addEventListener) window.addEventListener("message", receiveData, false); else window.attachEvent("onmessage", receiveData); 解决方