MDA/MDD/TDD/DDD/DDDDDDD
posts - 536, comments - 111, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

java内存泄漏笔记

Posted on 2009-01-14 14:18 leekiang 阅读(6048) 评论(2)  编辑  收藏 所属分类: java
利用jdk6查内存泄漏(见编写对GC友好,又不泄漏的代码)
(1)jmap -dump:file=heap_file_name pid 会产生一个heap_file_name文件
(2)jhat heap_file_name,然后打开浏览器http://localhost:7000/ 浏览。
   可看到里面显示了运行的所有的类和实例及大小。平台(例如tomcat)的不会包括在里面。
(3)如果觉得不够,还可以把heap_file_name文件加一个bin的后缀,然后让Eclipse MAT来分析。看这里
另外
jps:与unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。
jinfo:的用处比较简单,就是能输出并修改运行时的java进程的运行参数。用法是jinfo -opt  pid 如:查看2788的MaxPerm大小可以用  jinfo -flag MaxPermSize 2788。
jstat 也很有用,说明见这里


3,
SUN JDK所支持的典型选项以及说明:http: //java.sun.com/javase/technologies/hotspot/vmoptions.jsp 上面有很多选项
-XX:-HeapDumpOnOutOfMemoryError 从jdk1.4.2 update 12 和java 5 update 7开始支持这个选项。

4,
关于jmap
从JDK 5开始,SUN JDK开始提供JMap的工具。但是仅仅是实验性质的,而且只有在solaris平台上有。
后来Jmap被反向移植到jdk 1.4.2_09。因为是实验性质,所以jmap可能会出现dump失败的情况。
但是自从JDK 6之后,jmap的稳定性和可用性都没问题了。请注意各个版本的jvm都要用自己版本的jmap,
而jhat可以用于分析各个版本的jmap dump出来的文件。至于jhat用于分析1g以上的dump文件,
我们有过多次在笔记本上的成功经历,它对内存的要求可能并没有那么高。
http://space.itpub.net/27378/viewspace-521225

5,J2SE6中使用jhat来分析内存堆
http://hi.baidu.com/tister/blog/item/e7374482f4341ca70cf4d2e8.html

6,Java内存溢出(OutOfMemory),内存分析相关工具
http://uglytroll.ycool.com/post.3046111.html

7,JDK中的好工具 jmap、jhat
http://wangzaixiang.blogspot.com/2008/10/jdk-jmapjhat.html
http://hi.baidu.com/zeorliu/blog/item/4f38989413601719d21b70d5.html

8,SAP贡献给eclipse基金会的MemoryAnalyzer,原来叫Java Memory Analysis
能分析几G的Memory Dump而不会内存溢出?
http://www.eclipse.org/mat/
可惜还是只支持jdk1.4.2 update 12 和java 5 update 7以上

9,在一个方法里面的变量是不会引起内存泄露的。
内存泄露都是发生在类变量和实例变量(且此实例被缓存、如单例模式)里。
我建议你从HashMap、HashMap$Entry 入手查查。
我也研究过一阵子的内存泄露问题,最终解决了。
http://www.javaeye.com/topic/233080

10,你遇到的是最理想的情况,但有时候,这种方法不能找到原因,只找到造成崩溃的点.就好比,
一个HTTP 请求,没有设置超时(对不起,默认是不超时,不知道为什么SUN要这样设定),
然后这条线程就卡在这里了,然后,这条线程里的一个堆栈被另一条线程放入内容,
本来这些内容就是要这条闲线程去处理的,但是现在,这条线程卡住了,但是用你说的这种方法,
绝对找不到造成内存泄露的原因是因为http不超时,一直卡在那里.

我还有一个笨办法做精细的内存分配比较:就是定期用pmap命令dump出来JVM进程的内存映射表,然后diff。
http://www.javaeye.com/topic/256701

11,http://calvin.javaeye.com/blog/91903
 java 不是有垃圾收集器了吗?怎么还泄漏啊,唬我啊??
   嗯,此泄漏非比泄漏。C/C++的泄漏,是对象已不可到达,而内存又没有回收,真正的内存黑洞。
   而Java的泄漏,则是因为各种原因,对象对应用已经无用,但一直被持有,一直可到达。
   总结原因无外乎几方面:

   1). 被生命周期极长的集合类不当持有,号称是Java内存泄漏的首因。
      这些集合类的生命周期通常极长,而且是一个辅助管理性质的对象,在一个业务事务运行完后,如果没有将某个业务对象主动的从中清除的话,这个集合就会吃越来越多内存,可以用WeakReference,如WeakHashMap,使得它持有的对象不增加对象的引用数。
   2). Scope定义不对,这个很简单了,方法的局部变量定义成类的变量,类的静态变量等。
   3). 异常时没有加finally{}来释放某些资源,JDBC时代也是很普遍的事情。
   4). 另外一些我了解不深的原因,如:Swing里的Listener没有显式remove;内部类持有外部对象的隐式引用;Finalizers造成关联对象没有被及时清空等。
 

搭车
我的SQL调优公式T=S/V
http://space.itpub.net/27378/viewspace-157789

MetaWidget及SOA
http://wangzaixiang.blogspot.com/2008/10/metawidget.html

评论

# re: java内存泄漏笔记  回复  更多评论   

2009-11-07 08:41 by 繁体字
内存泄漏 可真烦人! 查来查去,只查到string 类 晕死!

# re: java内存泄漏笔记  回复  更多评论   

2010-03-24 14:21 by 繁体字转换器
Java的一个重要优点就是通过垃圾收集器(Garbage Collection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存。

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


网站导航: