java 内存储器泄露的监控

java 内存泄露的监控

如果有些系统的性能不是很稳定,随着时间的变化而变化,那么就要怀疑系统是否存在内存泄漏了。特别是哪些随时间的推移越来越慢的系统,很大程度上是Java内存对象有了泄漏。
 
    不是说Java虚拟机是自动回收内存吗?怎么还存在内存泄漏?
    事实上,有些内存泄漏是无法通过其它手段避免的,只能由编程开发人员在编程的时候主动避免。Java虚拟机的确可以将没有用的对象自动回收掉,可是有些泄漏是程序员的疏漏,一直保持了本应该释放的对象,因此Java虚拟机不认为这些对象是没有用的,因为他们跟其它有用的对象没什么区别,还有引用指着这些对象。这种情况就只能从源码着手了,找出内存泄漏的根源。Java虚拟机提供了很多工具来定位内存泄漏的位置。在Sun的Hotspot中,主要有jmap和jhat。

jmap

jmap命令用于查看当前java进程或者core dump文件,显示当前存在与内存中的对象分布情况,包括对象所属的类,对象的个数和所占内存的大小,并且依所占用的内存大小的顺序排列。用下面命令查找java的pid:

Java代码  java 内存储器泄露的监控
  1. ps -ef|grep java  


然后查看java进程的内存对象分布:

Java代码  java 内存储器泄露的监控
  1. jmap -histo pid  


结果如图:

Java代码  java 内存储器泄露的监控
  1. C:\Documents and Settings\Administrator>jmap -histo 180  
  2.   
  3.  num     #instances         #bytes  class name  
  4. ----------------------------------------------  
  5.    1:         13352       60321384  [B  
  6.    2:        108823       13516768  <constMethodKlass>  
  7.    3:         89912        9476704  [C  
  8.    4:        108823        8710200  <methodKlass>  
  9.    5:        152780        6715552  <symbolKlass>  
  10.    6:          8796        5325984  <constantPoolKlass>  
  11.    7:          8796        4219536  <instanceKlassKlass>  
  12.    8:         16753        3896104  [I  
  13.    9:          7026        2782816  <constantPoolCacheKlass>  
  14.   10:        109717        2633208  java.lang.String  
  15.   11:         40391         969384  java.util.HashMap$Entry  
  16.   12:         13806         932104  [Ljava.lang.Object;  
  17.   13:          9400         902400  java.lang.Class  
  18.   14:          8076         854312  [Ljava.util.HashMap$Entry;  
  19.   15:         11426         794936  [S  
  20.   16:         13935         685408  [[I  



但是有时候光知道对象的数量和内存占用量是不够的,因为这些数据只是提供了有可能泄漏的对象,没有告诉这些对象是什么地方分配的。要定位内存泄漏还需要更多的信息。这时候就需要jhat工具了。

jhat在使用jhat之前,还需要用jmap获得更加详细的数据。一般用下面命令获得一个二进制的输出文件:

Java代码  java 内存储器泄露的监控
  1. C:\Documents and Settings\Administrator>jmap -dump:file=heap.bin 180  
  2. Dumping heap to C:\Documents and Settings\Administrator\heap.bin ...  
  3. Heap dump file created  



然后用下面的命令用jhat来分析这个文件:

Java代码  java 内存储器泄露的监控
  1. C:\Documents and Settings\Administrator>jhat -J-mx512m heap.bin  
  2. Reading from heap.bin...  
  3. Dump file created Mon Dec 06 23:36:22 CST 2010  
  4. Snapshot read, resolving...  
  5. Resolving 713062 objects...  
  6. .................  
  7. Eliminating duplicate references................................................  
  8. ......................................................................Snapshot resolved.  
  9. Started HTTP server on port 7000  
  10. Server is ready.  



这个命令会启动一个Web服务器,并在7000端口上监听。这时候可以借助浏览器访问http://localhost:7000,这个页面可以看到很多详细的信息,包括哪些对象是哪些类创建的。可以从http://localhost:7000/histo/入手,这个页面不但可以看到当前内存中对象的情况,还可以点击每一种对象来查找哪些正在使用此对象的其它对象,如下图:

java 内存储器泄露的监控

另外http://localhost:7000/showInstanceCounts/includePlatform/页面可以想jmap命令一样,提供对象实例的数量和大小的信息,如下图:

java 内存储器泄露的监控


此外值得一提的是查询页面http://localhost:7000/oql/,这个页面可以让你输入类似数据库sql查询语句,根据需求定位到相关的信息,如下图:

java 内存储器泄露的监控

 

本文来自:http://blog.csdn.net/dream8062/article/details/6711370