jdk工具之jmap(java memory map)、 mat之四--结合mat对内存泄露的分析、jhat之二--结合jmap生成的dump结果在浏览器上展示

来源:互联网 发布:linux 对外开放端口 编辑:程序博客网 时间:2024/05/18 16:16

1、介绍

打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。

 

可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。使用方法 jmap -histo pid。如果连用SHELL jmap -histo pid>a.log可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。jmap -dump:format=b,file=outfile 3024可以将3024进程的内存heap输出出来到outfile文件里,再配合MAT(内存分析工具(Memory Analysis Tool),使用参见:http://blog.csdn.net/fenglibing/archive/2011/04/02/6298326.aspx)或与jhat (Java Heap Analysis Tool)一起使用,能够以图像的形式直观的展示当前内存是否有问题。

64位机上使用需要使用如下方式:

jmap -J-d64 -heap pid

2、命令格式

SYNOPSIS

       jmap [ option ] pid

       jmap [ option ] executable core

       jmap [ option ] [server-id@]remote-hostname-or-IP

3、参数说明

1)、options: 

executable Java executable from which the core dump was produced.

(可能是产生core dump的java可执行程序)

core 将被打印信息的core dump文件

remote-hostname-or-IP 远程debug服务的主机名或ip

server-id 唯一id,假如一台主机上多个远程debug服务 

2)、基本参数:

-dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件. 

-finalizerinfo 打印正等候回收的对象的信息.

-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.

-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量. 

-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来. 

-F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效. 

-h | -help 打印辅助信息 

-J 传递参数给jmap启动的jvm. 

pid 需要被打印配相信息的java进程id,创业与打工的区别 - 博文预览,可以用jps查问.

4、使用示例

1)、[fenglb@ccbu-156-5 ~]$ jmap -histo 4939

[输出较多这里不贴了]

2)、[fenglb@ccbu-156-5 ~]$ jmap -dump:format=b,file=test.bin 4939

Dumping heap to /home/fenglb/test.bin ...

Heap dump file created

 

tasklist命令查看进程id(Tasklist"是 winxp/win2003/vista/win7/win8下的命令,用来显示运行在本地或远程计算机上的所有进程,带有多个执行参数。)

 

 

常用的参数如下:

histo

jmap -histo pid 展示class的内存情况

展示的信息为编号,实例数,字节,类名

 

 

heap

jmap -heap pid 展示pid的整体堆信息

复制代码
复制代码
    jmap -heap 2464      JVM version is 16.3-b01            using thread-local object allocation.      Parallel GC with 13 thread(s)            Heap Configuration:         MinHeapFreeRatio = 40         MaxHeapFreeRatio = 70         MaxHeapSize      = 8436842496 (8046.0MB)         NewSize          = 5439488 (5.1875MB)         MaxNewSize       = 17592186044415 MB         OldSize          = 5439488 (5.1875MB)         NewRatio         = 2         SurvivorRatio    = 8         PermSize         = 21757952 (20.75MB)         MaxPermSize      = 88080384 (84.0MB)            Heap Usage:      PS Young Generation      Eden Space:         capacity = 87883776 (83.8125MB)         used     = 31053080 (29.614524841308594MB)         free     = 56830696 (54.197975158691406MB)         35.33425782706469% used      From Space:         capacity = 13828096 (13.1875MB)         used     = 196608 (0.1875MB)         free     = 13631488 (13.0MB)         1.4218009478672986% used      To Space:         capacity = 16384000 (15.625MB)         used     = 0 (0.0MB)         free     = 16384000 (15.625MB)         0.0% used      PS Old Generation         capacity = 156172288 (148.9375MB)         used     = 27098208 (25.842864990234375MB)         free     = 129074080 (123.09463500976562MB)         17.35148299805917% used      PS Perm Generation         capacity = 88080384 (84.0MB)         used     = 50847592 (48.492042541503906MB)         free     = 37232792 (35.507957458496094MB)         57.728622073218936% used  
复制代码
复制代码

 

 

说明如下

复制代码
Parallel GC with 13 thread(s)   #13个gc线程    Heap Configuration:#堆内存初始化配置     MinHeapFreeRatio = 40  #-XX:MinHeapFreeRatio设置JVM堆最小空闲比率     MaxHeapFreeRatio = 70  #-XX:MaxHeapFreeRatio设置JVM堆最大空闲比率     MaxHeapSize      = 8436842496 (8046.0MB)#-XX:MaxHeapSize=设置JVM堆的最大大小     NewSize          = 5439488 (5.1875MB) #-XX:NewSize=设置JVM堆的‘新生代’的默认大小     MaxNewSize       = 17592186044415 MB  #-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小     OldSize          = 5439488 (5.1875MB) #-XX:OldSize=设置JVM堆的‘老生代’的大小     NewRatio         = 2 #-XX:NewRatio=:‘新生代’和‘老生代’的大小比率     SurvivorRatio    = 8 #-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值     PermSize         = 21757952 (20.75MB) #-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小     MaxPermSize      = 88080384 (84.0MB) #-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小    Heap Usage:  PS Young Generation  Eden Space:#Eden区内存分布     capacity = 87883776 (83.8125MB)     used     = 31053080 (29.614524841308594MB)     free     = 56830696 (54.197975158691406MB)     35.33425782706469% used  From Space:#其中一个Survivor区的内存分布     capacity = 13828096 (13.1875MB)     used     = 196608 (0.1875MB)     free     = 13631488 (13.0MB)     1.4218009478672986% used  To Space:#另一个Survivor区的内存分布     capacity = 16384000 (15.625MB)     used     = 0 (0.0MB)     free     = 16384000 (15.625MB)     0.0% used  PS Old Generation#当前的Old区内存分布     capacity = 156172288 (148.9375MB)     used     = 27098208 (25.842864990234375MB)     free     = 129074080 (123.09463500976562MB)     17.35148299805917% used  PS Perm Generation#当前的 “永生代” 内存分布     capacity = 88080384 (84.0MB)     used     = 50847592 (48.492042541503906MB)     free     = 37232792 (35.507957458496094MB)     57.728622073218936% used
复制代码

mat为eclipse的一个内存分析插件,帮助查找内存泄漏和减少内存消耗。

首先基于jmap导出的堆信息

jmap -dump:live,format=b,file=test.bin 29030  

 准备代码:

复制代码
class User {      private String id;      private String name;        public String getId() {          return id;      }        public void setId(String id) {          this.id = id;      }        public String getName() {          return name;      }        public void setName(String name) {          this.name = name;      }        public User(String id, String name) {          super();          this.id = id;          this.name = name;      }    }  
复制代码

 main方法:

复制代码
public static void main(String[] args) {      List<User> list = new ArrayList<User>();      for (int i = 1; i < 10000; i++) {          User o = new User(i + "", System.currentTimeMillis() + "");          list.add(o);          o = null;      }      System.out.println("end");      try {          Thread.sleep(100000000l);      } catch (InterruptedException e) {          e.printStackTrace();      }  }  
复制代码

 执行之后用jmap输出堆信息

然后导入分析工具

我们可以看到图形化展示:



 然后我们点击

Problem Suspect 1

如下所示:



 然后点击详情



 我们可以看到有很多的User对象



 这些对象有可能会溢出,然后我们打开OQL窗口看他是否为null,执行如下OQL语句

Java代码  
  1. SELECT u FROM org.learn.util.User u WHERE (u.value = null)  

 结果如下:



 也就是说这个是null,但是仍然有强引用存在,gc的时候是不能回收的,这样就会出现内存的溢出问题


阅读全文
0 0
原创粉丝点击