转载至
https://blog.youkuaiyun.com/qq_38071004/article/details/81004765
https://blog.youkuaiyun.com/qq_38071004/article/details/81013719
一、jps
jps由jdk1.5提供,用于查看当前用户下的java进程的pid及基本信息
1、jps -help
jps的帮助命令,可用jps -h
代替:
2、jps -m
查看进程pid及main方法参数:
图中 5940 是我的eclipse进程;18648是jps进程,他的main方法参数就是-m
;27800是我启动的hbuilder软件;47852是我运行的测试函数,参数是zdg
和HK
3、jps -q
仅显示pid:
4 、jps -v
查看pid及JVM参数:
5、 jps -l
查看pid及程序所在包名:
图中29852就是我运行的测试Java程序。
二、jstack
使用jstack可查看指定进程(pid)的堆栈信息,用以分析线程情况:
NEW:未启动的。不会出现在Dump中。
RUNNABLE:在虚拟机内执行的。
BLOCKED:受阻塞并等待监视器锁。
WATING:无限期等待另一个线程执行特定操作。
TIMED_WATING:有时限的等待另一个线程的特定操作。
TERMINATED:已退出的。
1、jstack -h
帮助命令:
2、jstack [-l][-m][-F] pid
-l
:长列表,打印锁的附加信息;-m
:打印java和native c/c++框架的所有栈信息;-F
:没有响应的时候强制打印栈信息;
3、例
首先通过jps查看进程pid:
然后通过jstack 55872 打印堆栈信息:
图中仅是一部分信息截图,可以看到当前主线程状态是TIMED_WATING
,在程序第6行:
4、线程死锁查看:
程序:
public class JpsTest {
public static void main(String[] args) throws InterruptedException {
//创建资源
final Object a = new Object();
final Object b = new Object();
//启动线程
new Thread(new Runnable() {
@Override
public void run() {
//获取a的锁
synchronized (a) {
try {
System.out.println("i'm t1");
//等待一会儿,确保下一个线程获得另一个资源对象锁
Thread.sleep(100);
//获取b的锁
synchronized (b) {
System.out.println("t1------");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//启动线程
new Thread(new Runnable() {
@Override
public void run() {
//获取b的锁
synchronized (b) {
try {
System.out.println("i'm t2");
//等待一会儿,确保下一个线程获得另一个资源对象锁
Thread.sleep(100);
//获取a的锁
synchronized (a) {
System.out.println("t2------");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
程序中两个线程分别持有对方所需资源的锁并等待对方释放导致死锁。
查看jstack打印信息:
可以看到图中第一行显示发现了线程死锁,Thread-1等待资源 - waiting to lock <0x00000000eb4c0bf8> (a java.lang.Object),且锁住了资源 - locked <0x00000000eb4c0c08> (a java.lang.Object),Thread2则与之相反。
3、jmap与jhat
查看堆内存使用情况:
jmap -heap pid:通过可查看堆内存的配置情况及使用情况
jmap -histo pid:统计对象的创建数量
jmap -dump:format=b,file=heapDump pid:生成dump文件与jhat配合使用
jhat -port xxxx heapDump:浏览器访问localhost:xxxx即可查看dump
例:
程序(程序简陋,忽略细节):
public class JmapTest {
public static void main(String[] args) throws InterruptedException {
JmapTest test = new JmapTest(300);
fun(test);
System.out.println(test.a);
}
private JmapTest next;
private Integer a;
public JmapTest(int a) {
this.a = a;
}
//通过向一个链表递归添加对象
public static void fun(JmapTest m) throws InterruptedException {
System.out.println(m.a);
m.next = new JmapTest(++m.a);
//避免过早发送内存溢出
Thread.sleep(1000);
fun(m.next);
}
}
首先通过使用jps -l获得pid,再通过jmap -heap pid查看堆内存配置及使用情况:
配置信息:
使用情况:
接下来通过jmap -histo pid查看对象创建数量:
图中我们得程序已经创建了401个实例对象了。
通过 jmap -dump:format=b,file=heapDump pid 生成heapDump文件:
这样文件已经创建成功,再通过jhat -port xxxx heapDump 启动一个监听程序查看文件:
程序已经启动,接下来在浏览器查看:
一、jstat
jstat用于查看虚拟机各种状态信息。
通常格式为jstat -option pid [interval] [count]:
option:功能选项,用于选择查看不同的状态信息;
pid:进程号;
interval:输出间隔时间;
count:执行次数;
1、jstat -class pid
图中Loaded代表类装载数,Unloaded代表类卸载数,两个Bytes分别代表装载卸载类的字节数,最后Time代表装载卸载总耗时。
2、jstat -compiler pid
compiled:编译数量; Failed:失败数量; Invalid:失效数量; Time:编译耗时;
FailedType:失败类型; FailedMethod:失败任务所在类及方法
3、jstat -gc pid
图中添加了间隔执行时间及执行次数。
S0C、S1C:两块survivor区大小;S0U、S1U:两块区域已使用大小;EC、EU:Eden区大小及已使用大小;OC、OU:老年代大小及使用大小;MC、MU:元空间大小及使用大小;CCSC、CCSU:压缩类大小及已使用大小(对象头中压缩指针指向的元空间大小,文档上的注释如图:)
YGC、YGCT:年轻代gc次数及时间;FGC、FGCT:full gc次数及时间;GCT:总gc时间
4、jstat -gccapacity pid
显示JVM内存使用情况:
NGCMN:年轻代空间最小值;NGCMX:年轻代空间最大值;NGC:年轻代当前空间大小;
S0C、S1C、EC:survivor区两块空间及Eden区的当前大小;
OGCMN、OGCMX:老年代空间最小值及最大值;OGC:老年代当前新生成空间大小;OC:老年代空间大小;MCMX、MCMX、MC:分别代表元空间最小值、最大值、当前值;
CCSMN、CCSMX、CCSC:压缩类空间最小值、最大值、当前值;YGC:年轻代gc次数;FGC:full gc次数;
5、jstat -gcutil pid
S0、S1、E、O、M、CCS:分别代表两块survivor区、Eden区、Old区、元空间、压缩类空间已使用大小占当前空间总大小的比值。YGC、YGCT:年轻代gc次数及时间;FGC、GFCT:gull gc次数及时间;GCT:总gc时间。
6、jstat -gcnew pid
这里仅TT、MTT、DSS与前文不同,所以进介绍这三个值,下文同理,不再声明。
TT:对象在新生代存活的次数;
MTT:对象在新生代存活的最大次数;
DSS:期望的幸存区大小;
7、jstat -gcnewcapacity pid
列出项含义见上文。
8、jstat -gcold pid
列出项含义见上文。
9、jstat -gcoldcapacity pid
10、jstat -gcpermcapacity pid与 jstat -gcmetacapacity pid
1.8移除了永久区,没gcpermcapacity
这个参数了,取而代之的是元空间,因此使用gcmetacapacity
11、jstat -printcompilation pid
compiled:已编译的数目;
size:最近编译的方法字节码大小;
Type:编译类型;
Method:编译的方法;
二、javap
用于class文件的反编译
1、javap xx
注:命令行在class文件所在目录打开才能反编译。或者在bin目录下打开,使用时输入全类名(即包含类名)。
2、javap -c xx
-c参数可以查看每个方法具体的字节码指令。
还有不少参数就不一一尝试了,附javap -help一张: