1.
jmap介绍
1
1.1.
jmap命令基本概述 1
1.2. 基本参数介绍
1
2.
案例演示
1
2.1.
案例演示
1
2.2.
案例分析
2
3.
jhat使用
5
1. Jmap介绍
1.1. jmap命令基本概述
Jmap命令基本概述:jmap是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。Jmap提供了导出整个vm中的内存信息的支持。基于jvm内存的分析工具,比如eclipse memory analyzer.
1.2. 基本参数介绍
基本参数:
-dump:[live,]format=b,file= 使用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
2. 案例演示
2.1. 案例演示
1.Tomcat下部署war包:
在工程路径(我的路径是:/opt/s1/webapps)下,放一个程序war包,名称为test1.war。
重启tomcat,再查看工程路径下文件,多了一个test1文件夹,war包自动解压缩。
1.查看被测代码
1.我们可以在前台访问:http://172.16.1.201:8080/test1/init1.jsp
2.对程序进行加压。
重启apache:/usr/local/apache2/bin/apachectl start,使用apache自带的ab对页面进行加压。执行命令: ./ab -c 200 -n 10000 http://172.16.1.201:8080/test1/init1.jsp
3.查看tomcat日志:
再访问前台页面会发现前台页面响应时间特别长,并且已经不能打开,用top查看应用服务器发现cpu,mem使用率都非常高。(cpu高说明在进行大量的计算,有些复杂的算法可以交给数据库去操作)查看tomcat日志出现:Exception in thread "Tribes-MembershipReceiver" java.lang.OutOfMemoryError: Java heap space(出现了内存泄露的问题)
1.1. 案例分析
1.使用jmap命令查看jvm内存使用
用top查看消耗cpu,内存最高的pid为4280,可以通过jmap –heap pid命令查看内存使用情况:
Jmap -heap 4280
Attaching to process ID 4280, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 20.45-b01
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration: ##堆配置情况
MinHeapFreeRatio=40 //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
MaxHeapFreeRatio=70 //对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)
MaxHeapSize=512.0MB //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
NewSize = 1.0MB //对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
MaxNewSize =4095MB //对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
OldSize = 4.0MB //对应jvm启动参数-XX:OldSize=:设置JVM堆的‘老生代’的大小
NewRatio = 8 //对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio = 8 //对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
PermSize= 16.0MB //对应jvm启动参数-XX:PermSize=:设置JVM堆的‘永生代’的初始大小
MaxPermSize=64.0MB //对应jvm启动参数-XX:MaxPermSize=:设置JVM堆的‘永生代’的最大大小
Heap Usage: ##堆内存分布:
New Generation (Eden + 1 Survivor Space): ##新生代(伊甸区 + survior空间)
capacity = 30212096 (28.8125MB) ## 伊甸区容量
used = 30212088 (28.81249237060547MB) ##已经使用大小
free = 8 (7.62939453125E-6MB) ##剩余容量
99.99997352053958% used ##使用比例
Eden Space: ##伊甸区
capacity = 26869760 (25.625MB) ##伊甸区容量
used = 26869752 (25.62499237060547MB) ##伊甸区使用
free = 8 (7.62939453125E-6MB) ##伊甸区当前剩余容量
99.99997022675305% used ##伊甸区使用情况
From Space: ##survior1区
capacity = 3342336 (3.1875MB) ##survior1区容量
used = 3342336 (3.1875MB) ##surviror1区已使用情况
free = 0 (0.0MB) ##surviror1区剩余容量
100.0% used ##survior1区使用比例
To Space: ##survior2 区
capacity = 3342336 (3.1875MB) ##survior2区容量
used = 0 (0.0MB) ##survior2区已使用情况
free = 3342336 (3.1875MB) ##survior2区剩余容量
0.0% used ## survior2区使用比例
tenured generation:
capacity = 67108864 (64.0MB) ##老生代容量
used = 65165272 (62.146446228027344MB) ##老生代已使用容量
free = 1943592 (1.8535537719726562MB) ##老生代剩余容量
97.10382223129272% used ##老生代使用比例
Perm Generation: ##perm区使用情况
capacity = 14417920 (13.75MB) ##perm区容量
used = 14251480 (13.591270446777344MB) ##perm区已使用容量
free = 166440 (0.15872955322265625MB) ##perm区剩余容量
98.84560324928977% used ##perm区使用比例
Ps :64位机上使用需要使用如下方式:jmap -J-d64 -heap pid
2. 用jmap -histo pid打印每个实例占用内存情况:
Jmap -histo pid 可以打印class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量. 但是实际打印时会发现数据量非常大。可以将打印信息输出到文本中。在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。jmap -dump:format=b,file=a.dat pid可以将4280进程的内存heap输出到outfile文件里,再配合MAT(内存分析工具)。Dump完成后,可以通过命令:jhat -J-Xmx10240M filename (分配10G内存去打开这个dump文件,这个文件存放堆的对象)打开文件。
Jmap -histo:live 4280 > a.txt,查看前top30,查看占用内存比较多的实例。试验中看到占用内存比较大的为cn.test.testbean类。
Ps:如果打印报错:
可以将Jmap -F –histo pid > 1.txt(-F强制输出)
3.Jmap命令打印信息:
Num,instances(实例数),bytes,class name(class名)
class name对应的就是Class文件里的class的标识
B代表byte
C代表char
D代表double
F代表float
I代表int
J代表long
Z代表boolean
前边有[代表数组,[I 就相当于int[]
查看排名前20,30的方法是不是自己工程里面的,如果是就能判定是哪个方法造成的内存泄露。
2. Jhat使用
用途:是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。
使用步骤:
1)导出堆:jmap -dump:live,file=a.map 4280
2)分析堆文件:jhat a.map
3)查看html
有时你dump出来的堆很大,在启动时会报堆空间不足的错误,可以使用如下参数:
jhat -J-Xmx512m
4)对于jhat启动后显示的html页面中功能:
Ø 显示出堆中所包含的所有的类:all classes(including platform)
Ø 从根集能引用到的对象。All members of the rootset
Ø 显示平台包括的所有类的实例数量:instance counts for all classes(including platform)
Ø 堆实例的分布表: heap histogram
Ø 执行对象查询语句
加载中,请稍候......