posts - 241,  comments - 116,  trackbacks - 0
最近无意间在网上看到了一个监控java程序内存使用的工具 - JProbe,马上回想起那个有关内存溢出的难题,于是我就下载了JProbe8.0.0希望从分析内存入手找到我要的答案。软件下载安装后,在安装目录 里详尽的用户指南(懂点软件和英语的人很快就能上手),主要是两个步骤: 洛克王国暴角龙配招

1.用JProbe Config工具根据提示生成J2SE或者J2EE程序的控制脚本(一个.jpl文件和一个.bat文件),在命令行里进入.bat文件所在的目录,然后执行该批处理让要监控的java程序跑起来

2.运行JProbe Console工具,点击“Attach to Session...”按钮,弹出java程序的内存实时监控图表“Runtime Summary”,我们主要是看“Data”卡片里的内容(注意:第一次使用该软件可能会遇到一些小问题:比如发布为jar包的程序如果运行时会去读配置 文件,从控制脚本启动的话,可能会发生配置文件找不到的异常,解决办法是:不要打jar包,直接就用文件夹发布;还有可能因为一些杀毒软件的网络防火墙导 致JProbe无法连接到控制脚本的session,造成监控图表打不开,解决办法是:取消防火墙对于JProbe访问网络的限制)
可以设置要监视的包或者类,然后点击“Refresh Runtime Data”按钮刷新这些对象占用内存的情况,当你觉得某个类比较可疑的话,你可以在不断的使用程序的过程中监视它的生命周期,看看它是否像预期的那样在结 束了生命周期后占用的内存就被释放。众所周知:java的内存回收是自动进行的,无需程序员干预,我们称其为垃圾回收,这个垃圾回收可能是不定期的,就是 当程序占用内存资源比较少的情况下可能jvm的垃圾回收频率就比较低;反之,java程序消耗内存资源比较多的情况下,垃圾回收的频率和力度就比较高,这 种垃圾回收的不确定性很可能会影响我们的判断,但我们可以点击JProbe监控界面右上方的“Request a Garbage Collection”(像一个垃圾桶的图标)按钮来向jvm发出垃圾回收的请求,等几秒后再去点击“Refresh Runtime Data”,这个时候如果那个预期应该已经销毁的对象的类名还是没有从监控界面下方的class列中消失或者其对象数量没有减少的话(请多试几次,中间可 以夹杂些其他增加程序内存使用的操作以确保jvm确实执行了垃圾回收),那恭喜你!90%的可能性你已经找到了程序的某个缺陷

这个查找元凶的过程可能是相当耗时的,是对程序员的耐心的挑战。我熬了一下午一晚上,功夫不负有心人,基本上把我那个小程序的所有内存溢出的漏洞 都找到并补上了。事实告诉我之前那个子窗体关闭后资源无法释放的根本原因是:子窗体虽然调用了dispose()方法,但是子窗体对象的引用一直都在:或 者是被静态HashMap引用、或者是它的内部子线程类没有释放、或者是它的某个事件监听类没有释放(借用JProbe的火眼金睛一检验,发现问题真是一 大堆啊!),so.我们要彻底释放某个对象占用资源的关键在于找到并释放所有对它的引用!
程序中造成内存溢出可能性最大的是HashMap,Hashtable等等集合类,尤其是静态的,更是要慎之又慎!!!它们引用的对象可能你感觉已经销毁 了,其实很可能你忘记remove键值,而如果这些集合对象还是静态的挂在其他类里面,那么这个引用可能一直都在,借用JProbe测试一下,结果往往出 人意料,解决办法:彻底删除键,remove、clear,如果允许最好把集合对象设为null

对于不再使用的线程对象,如果要彻底杀了它,很多书上都推荐用join方法,我之前也是这样做的,但后来借助JProbe工具我吃惊的发现这样做 很可能要杀的线程仍旧好好的活在你日益增大的内存里,很可能调用了线程的sleep方法后用join方法就会有点问题,解决办法:在join方法前再加一 句执行interrupt方法,不过这个时候可能会有新的问题:执行interrupt方法后你的线程类会抛InterruptedException, 上有政策下有对策,加一个开关变量做判断就能完美解决,可参考下面的代码:
posted on 2011-04-15 15:20 墙头草 阅读(243) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航:
 
人人游戏网 软件开发网 货运专家