目录
一、jdk工具之jps(JVM Process Status Tools)命令使用
二、jdk命令之javah命令(C Header and Stub File Generator)
三、jdk工具之jstack(Java Stack Trace)
四、jdk工具之jstat命令(Java Virtual Machine Statistics Monitoring Tool)
四、jdk工具之jstat命令2(Java Virtual Machine Statistics Monitoring Tool)详解
五、jdk工具之jmap(java memory map)、 mat之四--结合mat对内存泄露的分析
六、jdk工具之jinfo命令(Java Configuration Info)
七、jdk工具之jconsole命令(Java Monitoring and Management Console)
八、jdk工具之JvisualVM、JvisualVM之二--Java程序性能分析工具Java VisualVM
九、jdk工具之jhat命令(Java Heap Analyse Tool)
十、jdk工具之Jdb命令(The Java Debugger)
十一、jdk命令之Jstatd命令(Java Statistics Monitoring Daemon)
十一、jdk命令之Jstatd命令(Java Statistics Monitoring Daemon)
十二、jdk工具之jcmd介绍(堆转储、堆分析、获取系统信息、查看堆外内存)
十三、jdk命令之Java内存之本地内存分析神器:NMT 和 pmap
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)一起使用,能够以图像的形式直观的展示当前内存是否有问题。
查看该进程(pid)下堆内存的使用情况:
jmap -heap pid
快速定位内存泄漏的方法:只统计存活的对象
jmap -histo:live pid
还可以导出:
jmap -histo:live pid >1.txt将信息输出到指定文件中
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、使用示例
tasklist命令查看进程id(Tasklist"是 winxp/win2003/vista/win7/win8下的命令,用来显示运行在本地或远程计算机上的所有进程,带有多个执行参数。)
常用的参数如下:
histo
jmap -histo pid 展示class的内存情况
展示的信息为编号,实例数,字节,类名
aaarticlea/png;base64,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" alt="" />
-finalizerinfo
打印等待回收的对象信息
jmap -finalizerinfo
Attaching to process ID , please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.171-b11
Number of objects pending for finalization:
[root@ip---- applogs]#
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 thread(s) #13个gc线程 Heap Configuration:#堆内存初始化配置
MinHeapFreeRatio = #-XX:MinHeapFreeRatio设置JVM堆最小空闲比率
MaxHeapFreeRatio = #-XX:MaxHeapFreeRatio设置JVM堆最大空闲比率
MaxHeapSize = (.0MB)#-XX:MaxHeapSize=设置JVM堆的最大大小
NewSize = (.1875MB) #-XX:NewSize=设置JVM堆的‘新生代’的默认大小
MaxNewSize = MB #-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
OldSize = (.1875MB) #-XX:OldSize=设置JVM堆的‘老生代’的大小
NewRatio = #-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio = #-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
PermSize = (.75MB) #-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小
MaxPermSize = (.0MB) #-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小 Heap Usage:
PS Young Generation
Eden Space:#Eden区内存分布
capacity = (.8125MB)
used = (.614524841308594MB)
free = (.197975158691406MB)
35.33425782706469% used
From Space:#其中一个Survivor区的内存分布
capacity = (.1875MB)
used = (.1875MB)
free = (.0MB)
1.4218009478672986% used
To Space:#另一个Survivor区的内存分布
capacity = (.625MB)
used = (.0MB)
free = (.625MB)
0.0% used
PS Old Generation#当前的Old区内存分布
capacity = (.9375MB)
used = (.842864990234375MB)
free = (.09463500976562MB)
17.35148299805917% used
PS Perm Generation#当前的 “永生代” 内存分布
capacity = (.0MB)
used = (.492042541503906MB)
free = (.507957458496094MB)
57.728622073218936% used
mat为eclipse的一个内存分析插件,帮助查找内存泄漏和减少内存消耗。
首先基于jmap导出的堆信息
jmap -dump:live,format=b,file=test.bin
准备代码:
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语句
SELECT u FROM org.learn.util.User u WHERE (u.value = null)
也就是说这个是null,但是仍然有强引用存在,gc的时候是不能回收的,这样就会出现内存的溢出问题
示例2:如何用mat分析内存问题
我用MAT打开了heap.bin,很容易看出,char[]的数量出其意料的多,占用90%以上的内存 。一般来说,char[]在JVM确实会占用很多内存,数量也非常多,因为String对象以char[]作为内部存储。但是这次的char[]太贪婪 了,仔细一观察,发现有数万计的char[],每个都占用数百K的内存 。这个现象说明,Java程序保存了数以万计的大String对象 。结合程序的逻辑,这个是不应该的,肯定在某个地方出了问题。
在可疑的char[]中,任意挑了一个,使用Path To GC Root功能,找到该char[]的引用路径,发现String对象是被一个HashMap中引用的 。这个也是意料中的事情,Java的内存泄露多半是因为对象被遗留在全局的HashMap中得不到释放。不过,该HashMap被用作一个缓存,设置了缓 存条目的阈值,导达到阈值后会自动淘汰。从这个逻辑分析,应该不会出现内存泄露的。虽然缓存中的String对象已经达到数万计,但仍然没有达到预先设置 的阈值(阈值设置地比较大,因为当时预估String对象都比较小)。
但是,另一个问题引起了我的注意:为什么缓存的String对象如此巨大?内部char[]的长度达数百K。虽然缓存中的 String对象数量还没有达到阈值,但是String对象大小远远超出了我们的预期,最终导致内存被大量消耗,形成内存泄露的迹象(准确说应该是内存消 耗过多) 。
就这个问题进一步顺藤摸瓜,看看String大对象是如何被放到HashMap中的。通过查看程序的源代码,我发现,确实有String大对象,不 过并没有把String大对象放到HashMap中,而是把String大对象进行split(调用String.split方法),然后将split出 来的String小对象放到HashMap中 了。
这就奇怪了,放到HashMap中明明是split之后的String小对象,怎么会占用那么大空间呢?难道是String类的split方法有问题?