- 浏览: 66247 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
风雨人生:
学习了,很好很强大....
解决JfreeChart柱状图数值显示在柱子顶端的问题 -
wuqi123321:
引用asdfasdfa
解决JfreeChart柱状图数值显示在柱子顶端的问题 -
yefeng:
我下了ru.nlmk.eclipse.plugins.prof ...
Java内存泄漏分析
http://www.51testing.com/html/9/519.html
ava语言相比C++的一个很大优势就是Java可以自动管理内存的回收,这大大减少了程序员的负担。然而,Java并不是杜绝了所有的内存问题, 还是会有内存泄漏的问题,只不过原因和C++是不一样的,所以出现得比较少。Java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一 遍后发现没有被引用的孤立对象就作为垃圾回收。详细说明可以看ibm developerworks上的文章 (http://www-900.ibm.com/developerworks/cn/java/j-leaks/index_eng.shtml )。在现在代码检查工具越来越先进的情况下,C++的内存漏洞检查已经变得容易很多,但Java的内存漏洞由于机制不一样,反而无法通过工具直接检查出来,只要靠辅助工具检测,发现疑点,然后再手动解决。
下面是我调试一个大型软件系统内存泄漏问题的过程,把其中失败的做法也写出来了,因为都是有参考价值的:
现象:程序启动后一直运行正常,但启动某个模块后,每分钟多消耗1M的内存,持续增长到出现java.lang.OutOfMemoryError为止,而CPU占用率也是逐步上升至100%。
判断:由于CPU和内存都出现问题,无法判断哪个是主因,也可能是多个原因造成的,估计最可能是多线程或者内存泄漏的问题。
辅助工具:由于不是我自己写的程序,所以没法直接估计是代码的哪一部分的问题,所以需要使用辅助工具,我比较常用的是Eclipse的插件 ru.nlmk.eclipse.plugins.profiler(免费)和Borland公司的Borland Optimizeit Suite(收费)。因为我是用Eclipse来开发程序,所以使用前者比较方便,个人感觉使用时占用的系统资源少一点,而且在CPU检查方面是略强一 点,但是后者在内存检查方面强大很多。
分析过程:当时由于CPU和内存都出现问题,无法判断哪个是主因,需要检测两方面的数据。内存泄漏需要等程序运行一段时间后才能看出来,所以检查很消耗时间。为了减少干扰,我把系统中所有不是必要的各线程逐个关闭来试验,然后把确认对内存问题没有影响的线程都关闭。
首先考虑解决内存问题。因为Java的内存泄漏问题往往跟HashMap相关,所以HashMap可能是一个突破口,而这么大量的内存泄漏,很可能 会是某些HashMap存放过多已经没用的对象造成的(如果是这个原因,那改为用WeakHashMap就可以解决问题了)。我从HashMap和 LinkedHashMap派生了子类,其中加入了数据量检查的信息,把系统中所有构造HashMap和LinkedHashMap的地方都改为使用这些 子类。但是运行后发现系统中构造的HashMap只有十几个,而且每个指向的对象也不多,只有少数几个是接近1千的,而仔细检查代码后,发现这几个指向对 象较多的HashMap也不会造成太大的内存泄漏问题。
这样我的思路就中断了,只好求助于工具来寻找疑点。因为发现CPU占用到100%一段时间后,程序就呈死机状态没法运行下去了,内存问题也就无从检测,所以就决定先检查CPU,用Eclipse的profiler插件来查。如图:
图1 Eclipse的profiler插件的Threads View
因为问题出在某个模块启动之后,所以这时先把统计功能关闭可以使结果更有意义(如果全部采样,初始化阶段的资源消耗对结果影响很大),也可以加快程 序启动。等问题模块启动后,开始启动统计功能,此时点击Threads View中某个线程,在Thread method View中就会显示该线程中各调用的方法所运行的时间。
图2 点击Threads View中的某个Thread,Thread methods View中就会显示相关的内容
按Total time排序查看就可以找到哪些方法是占用CPU最多的。
图3 按Total time排序查看Thread methods的数据
但是当时我犯了非常严重的错误,以前在filter中把系统类(例如java.*、sun.*等等)过滤了,忘了取消,结果查出来的结果非常莫名其妙,最占用CPU的函数(达30%多)居然只有一个long型的赋值语句!这是在profiler的属性中设置的,如图:
图4 Eclipse的profiler插件的运行属性设置
后来想起有这个问题,把fliter重新设好,检测结果就正常了,不过没有什么有价值的线索,占用CPU较多的都是java系统包的方法(后来查出 问题后回想才发现这里其实是有线索的)。于是就怀疑是内存快用光时JVM的内存管理模块会大量占用CPU,所以导致java程序的CPU占有率偏高(现在 还不知道是否确实如此),另一方面,这些检测工具本身就大量消耗系统资源,也是导致CPU占用为100%的主要原因。于是,又改为用Borland Optimizeit Suite检查内存问题了。
先启动Optimizeit Suite中的profiler模块:
图5 启动Profiler模块
图6 在Profiler主界面中添加新Setting
注意使用Borland Optimizeit Suite时,jar中要把main class设好,classpath中要把所有用到的外部jar包全部输入,否则无法启动和正常运行。这个工具不太友好,无法启动时输出信息很不明确,所以最好自己先检查清楚了。
图7 在Profiler的Setting中设置main class和classpath
一般测试时都有运行多次,当发现某些包跟问题无关时,可以把它们过滤掉,这样最后得到的结果更容易阅读。
图8 设置filter
用Profiler启动程序。运行到问题模块后,点击工具栏最右边的按钮,标记当时各对象占用内存的情况。
图9 标记当前内存情况(图中红柱上的黑线)
点击工具栏上像感叹号的按钮,选择显示的内容。对这个问题,我觉得show size是最重要的。
图10 设置显示的内容
再运行一段时间后,按Size diff排序。发现占用内存比较多的了后,双击该行,打开该对象的详细信息(目前bug已经改好,我只是随便点一个类作为示范)。这时展开整棵树,就可以 看到该类所有实例分别是在什么方法中生成的(如果跟踪CPU信息,也有这种资源分配树显示)。
图11 某个类的所有对象的构造位置分布
因为占用内存最多的往往是系统基本数据类型,例如char,int[]等等,所以需要人工去判断哪些类是真正的疑点。我发现占用新申请内存排名第 20-30之间有几个类的对象数是完全相同的,而且持续同步增长,估计是某些线程中重复构造对象造成的,比其他以不规则速度增长的类更加可疑,于是就仔细 检查了这几个的类的详细信息,发现果然是来自同一个函数。再仔细看代码,就找到内存泄漏的原因,原来是某行代码写错了,不断构造新的button。而保存 这些button是用Vector!说明我最早使用的检查HashMap的思路是对的。可惜只是从自己的编程习惯出发,没有考虑到Vector,否则问题 就更容易发现了。
不过当时还曾经检测到一个突变过程,至今没有想明白原因。在没有任何人对该计算机进行操作的情况下,CPU和内存占有率在某个时刻同时暴增。如图:
图12 CPU占用率突变
图13 内存占用突变
欢迎知道原因的朋友回复,:)
发表评论
-
使用filter拦截servlet和jsp页面的内容,进行过滤后输出
2013-06-04 13:42 1119http://blog.csdn.net/shuwei00 ... -
连接池问题
2012-07-22 14:15 715connection耗尽不一定就是由connectio ... -
LuceneTest
2011-06-10 00:38 848/** * */ package com.test ... -
读写文件
2011-05-15 18:16 1015import java.io.BufferedInputStr ... -
流方式下载文章
2010-10-11 18:44 700流方式下载文章 -
JSP 图片验证码
2009-12-22 17:51 970/*1.定义图片类*/ package servlet; ... -
tomcat 开启SSL
2009-12-10 23:37 18651.生成 KeyStore D:\jdk1.6.0_11 ... -
commons-dbutils 使用
2009-10-09 17:26 1149import java.sql.Connection; im ... -
JBPM数据库表说明
2009-09-28 18:09 1030JBPM数据库表说明 -
中文乱码问题解决,过滤器配置,get post提交乱码,filter,struts乱码,jsp乱码
2009-09-25 18:25 1228http://heisetoufa.iteye.com/blo ... -
JBoss JBPM 实践系列(一)--- 安装配置(Tomcat 6.0 + MySQL 5.1)
2009-09-25 02:02 692http://zhaipuhong.iteye.com/blo ... -
常用网站
2009-06-17 00:35 0http://www.dojochina.com/ ... -
如何卸载和安装Wscript.Shell,FSO和stream对象
2008-11-23 00:16 1736据需要不同我们经常会卸载和安装Wscript.Shell,FS ... -
javascript调用本地的exe程序
2008-11-23 00:00 2352http://dayone.iteye.com/blog/16 ... -
log4j配置文件
2008-11-18 14:02 1080log4j.rootLogger=error,stdout l ... -
JAVA内存泄漏——内存泄漏原因和内存泄漏检测工具(zt)
2008-11-13 19:33 2117http://www.blogjava.net/galaxyp ... -
解决JfreeChart柱状图数值显示在柱子顶端的问题
2008-11-13 16:04 11868http://topic.csdn.net/u/2008061 ... -
主题:通过GC输出分析内存泄露问题
2008-11-12 17:44 0http://www.iteye.com/post/70863 ... -
详解MANIFEST.MF文件
2008-10-26 23:19 692http://www.java3z.com/cwbwebhom ... -
JAR 文件揭密
2008-10-26 23:19 717http://www-128.ibm.com/develope ...
相关推荐
java内存泄漏分析工具
该工具用来排查线上程序出现内存泄漏或溢出,死锁等相关问题,快速分析堆栈异常情况,找到问题代码进行修复。
java 内存泄露分析方法、在工作中经常会碰到各种原因导致的内存泄露问题,本方法或许可以帮你快速定位内存泄露的原因从而解决问题
java内存泄露问题的定位与详细的分析过程
解压后 把直接把该文件夹放到eclipse安装目录dropins下,重启eclipse.exe -clean 即可
java内存分析
MAT 是一个开源的java内存分析工具,能够快速的分析dump文件,可以直观的看到各个对象在内存占用的量大小,以及类实例的数量,对象之间的引用关系,找出对象的GC Roots相关的信息,此外还能生成内存泄露报表,疑似...
基于Java的内存泄露分析及定位,希望对各位有用!
java内存泄露定位与分析
java内存泄露定位与分析[整理].pdf
java检测内存泄露工具--jprofiler5 里面含破解注册码,按照使用说明即可使用!
Java内存泄漏原因分析大全,讲述java语言内存泄漏的方方面面的原因。
Eclipse Memory Analyzer 是一个功能丰富且轻量的 Java 堆内存分析工具,可以用来辅助发现内存泄漏减 少内存占用。 使用 Memory Analyzer 来分析生产环境的 Java 堆转储文件,可以从数以百万计的对象中快速计算出对 ...
Java内存分析工具,解决内存泄漏问题
java内存泄露分析与避免办法,同时也提到如何通过jdk自带工具检测内存是否泄露。
尽管java虚拟机和垃圾回收机制管理着大部分的内存事务,但是在java软件中还是可能存在内存泄漏的情况。的确,在大型工程中,内存泄漏是一个普遍问题。避免内存泄漏的第一步,就是要了解他们发生的原因。这篇文章就是...
内存泄漏分析工具mat
详细介绍Java的内存管理与...经过分析Java内存泄漏是破坏系统的主要因素。这里与大家分享我们在开发过程中遇到的Java内存泄漏的检测和处理解决过程. 本文先介绍Java的内存管理,以及导致Java内存泄露的原因。 ........
java内存泄露定位与分析共13页.pdf.zip