背景
给一个系统定位问题的时候,知识、经验是关键基础,数据(运行日志、异常堆栈、GC日志、线程快照[threaddump / javacore文件]、堆转储快照[heapdump / hprof])是依据,工具是运用知识处理数据的手段。
经常使用适当的虚拟机监控和分析的工具可以加快我们分析数据、定位解决问题的速度。
jps
jps(JVM Process Status Tool)可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID)。对于本地虚拟机进程来说,LVMID与操作系统的进程ID(Process Identifier, PID)是一致的。
用法
主要选项
选项
作用
备注
-q
只输出LVMID,省略主类的名称
-m
输出虚拟机进程启动时传递给主类main()函数的参数
-l
输出主类的全名,如果进程执行的是jar包,输出jar路径
-v
输出虚拟机进程启动时JVM参数
jstat
jstat(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工具。
它可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
jstat [option vmid [interval][s|ms] [count]]
option代表用户希望查询的虚拟机信息,主要分为3类:类装载、垃圾收集、运行期编译状况。具体如下表:
选项
作用
-class
监视类装载、卸载数量、总空间以及类装载所耗费的时间。
-gc
监视Java堆状况,包括Eden区、两个Survivor区、老年区、永久代等的容量、已用框架,GC时间合计等信息。
-gccapacity
监视内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。
-gcutil
监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。
-gccause
与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因。
-gcnew
监视新生代GC状况。
-gcnewcapacity
-gcold
-gcoldcapacity
-gcpermcapacity
-compiler
-printcompilation
如果是本地虚拟机进程,则VMID与LVMID是一致的,如果是远程虚拟机进程,那么VMID的格式是:
[protocal:][//]vmid[@hostname[:port]/servername]
interval代表查询间隔
count代表查询次数
如果省略这两个参数,说明只查询一次。
javap
javap是JDK自带的反汇编器,可以查看java编译器为我们生成的字节码。通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作。
用法
语法:
javap [ 命令选项 ] class. . .
javap命令用于解析类文件。其输出取决于所用的命令选项。若没有使用命令选项,javap将输出传递给它的类的public 域及方法。javap将其输出到标准输出设备上。
命令选项:
-help 输出 javap 的帮助信息。
-l 输出行及局部变量表。
-b 确保与 JDK 1.1 javap 的向后兼容性。
-public 只显示 public 类及成员。
-protected 只显示 protected 和 public 类及成员。
-package 只显示包、protected 和 public 类及成员。这是缺省设置。
-private 显示所有类和成员。
-J[flag] 直接将 flag 传给运行时系统。
-s 输出内部类型签名。
-c 输出类中各方法的未解析的代码,即构成 Java 字节码的指令。
-verbose 输出堆栈大小、各方法的 locals 及 args 数,以及class文件的编译版本
-classpath[路径] 指定 javap 用来查找类的路径。如果设置了该选项,则它将覆盖缺省值或 CLASSPATH 环境变量。目录用冒号分隔。
-bootclasspath[路径] 指定加载自举类所用的路径。缺省情况下,自举类是实现核心 Java 平台的类,位于 jrelib下面。
-extdirs[dirs] 覆盖搜索安装方式扩展的位置。扩展的缺省位置是 jrelibext。
实例
package com.huawei.thread;
public class Test44 {
public static volatile int race = 0;
public static void increase() {
race++;
}
private static final int THREADS_COUNT = 20;
public static void main(String[] args) {
Thread[] threads = new Thread[THREADS_COUNT];
for (int i = 0; i < THREADS_COUNT; i++) {
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
increase();
}
}
});
threads[i].start();
}
while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(race);
}
}
javap -c Test44生成的字节码为:
D:\workspace\Thread\bin\com\huawei\thread>javap -c Test44
警告: 二进制文件Test44包含com.huawei.thread.Test44
Compiled from "Test44.java"
public class com.huawei.thread.Test44 {
public static volatile int race;
static {};
Code:
0: iconst_0
1: putstatic #13 // Field race:I
4: return
public com.huawei.thread.Test44();
Code:
0: aload_0
1: invokespecial #18 // Method java/lang/Object."":()V
4: return
public static void increase();
Code:
0: getstatic #13 // Field race:I
3: iconst_1
4: iadd
5: putstatic #13 // Field race:I
8: return
public static void main(java.lang.String[]);
Code:
0: bipush 20
2: anewarray #25 // class java/lang/Thread
5: astore_1
6: iconst_0
7: istore_2
8: goto 37
11: aload_1
12: iload_2
13: new #25 // class java/lang/Thread
16: dup
17: new #27 // class com/huawei/thread/Test44$1
20: dup
21: invokespecial #29 // Method com/huawei/thread/Test44$1."":()V
24: invokespecial #30 // Method java/lang/Thread."":(Ljava/lang/Runnable;)V
27: aastore
28: aload_1
29: iload_2
30: aaload
31: invokevirtual #33 // Method java/lang/Thread.start:()V
34: iinc 2, 1
37: iload_2
38: bipush 20
40: if_icmplt 11
43: goto 49
46: invokestatic #36 // Method java/lang/Thread.yield:()V
49: invokestatic #39 // Method java/lang/Thread.activeCount:()I
52: iconst_1
53: if_icmpgt 46
56: getstatic #43 // Field java/lang/System.out:Ljava/io/PrintStream;
59: getstatic #13 // Field race:I
62: invokevirtual #49 // Method java/io/PrintStream.println:(I)V
65: return
}
原文:http://www.cnblogs.com/lujiango/p/7680429.html