工欲善其事,必先利其器。
在JVM的学习过程中,将会利用很多工具对程序代码进行辅助分析。本文主要列举了jps、jinfo、jmap、jstack等官方工具及jclasslib bytecode viewer第三方工具。
JVM工具集合包括但不限于以下内容
1. javac
javac是Java语言的编译工具,它将Java开发的class、interface编译为二进制文件,输出的文件后缀为.class。
运行指令为:javac [options ] [sourcefiles] [classes] [@argfiles]
2. javap
javap是Java class文件的反编译工具,它通过控制台打印输出class的属性和方法。
import java.awt.*;
import java.applet.*;
public class DocFooter extends Applet {
String date;
String email;
public void init() {
resize(500, 100);
date = getParameter("LAST_UPDATED");
email = getParameter("EMAIL");
}
public void paint(Graphics g) {
g.drawString(date + " by ", 100, 15);
g.drawString(email, 290, 15);
}
}
运行指令javap -c DocFooter.class后输出为:
Compiled from "DocFooter.java"
public class DocFooter extends java.applet.Applet {
java.lang.String date;
java.lang.String email;
public DocFooter();
Code:
0: aload_0
1: invokespecial #1 // Method java/applet/Applet."<init>":()V
4: return
public void init();
Code:
0: aload_0
1: sipush 500
4: bipush 100
6: invokevirtual #2 // Method resize:(II)V
9: aload_0
10: aload_0
11: ldc #3 // String LAST_UPDATED
13: invokevirtual #4 // Method getParameter:(Ljava/lang/String;)Ljava/lang/String;
16: putfield #5 // Field date:Ljava/lang/String;
19: aload_0
20: aload_0
21: ldc #6 // String EMAIL
23: invokevirtual #4 // Method getParameter:(Ljava/lang/String;)Ljava/lang/String;
26: putfield #7 // Field email:Ljava/lang/String;
29: return
public void paint(java.awt.Graphics);
Code:
0: aload_1
1: new #8 // class java/lang/StringBuilder
4: dup
5: invokespecial #9 // Method java/lang/StringBuilder."<init>":()V
8: aload_0
9: getfield #5 // Field date:Ljava/lang/String;
12: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: ldc #11 // String by
17: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
23: bipush 100
25: bipush 15
27: invokevirtual #13 // Method java/awt/Graphics.drawString:(Ljava/lang/String;II)V
30: aload_1
31: aload_0
32: getfield #7 // Field email:Ljava/lang/String;
35: sipush 290
38: bipush 15
40: invokevirtual #13 // Method java/awt/Graphics.drawString:(Ljava/lang/String;II)V
43: return
}
3. jps(JVM Process Status Tool)
jps指令是查看HotSpot VM中运行的程序列表工具,可以列出正在运行的虚拟机进程,并显示虚拟机执行主类名称以及这些进程的本地虚拟机LVMID(Local Virtual Machine Identifier)。
运行指令为:jps [options] [hostid]
options参数
选项 | 作用 |
-q | 只输出LVMID,省略主类名称 |
-m | 输出虚拟机进程启动时传递给主类main()函数的参数 |
-l | 输出主类的全名,如果进程执行的是jar包,则输出jar路径 |
-v | 输出虚拟机进程启动时的JVM参数 |
hostid参数
可通过RMI协议开启远程虚拟机进程状态,hostid为RMI注册表中注册的主机名。
若某Java进程关闭了UsePerfData参数(即-XX:-UsePerfData),那么jps将无法探知该Java进程。
4. jinfo(Configuration Info for Java)
jinfo指令是打印输出Java程序配置信息的工具,这些配置信息包含Java环境变量及JVM参数设置。
运行指令为:
- jinfo [option] pid
- jinfo [option] executable core
- jinfo [option] [servier-id] remote-hostname-or-IP
5. jmap(Memory Map for Java)
jmap指令是内存映像工具,用于生成堆转储快照。除此以外,它还可以查询finalize执行队列、Java堆和方法区的详细信息(如空间使用率、当前用的是哪种收集器等)。
运行指令为:
- jmap [options] pid
- jmap [options] executable core
- jmap [options] [pid] [server-id@] remote-hostname-or-IP
选项 | 作用 |
-dump | 生成Java堆转储快照。格式为-dump:[live,]format=b,file=filename |
-histo | 显示堆中对象统计信息,包括类、实例数量、合计容量 |
6. jstack(Stack Trace for Java)
jstack指令是打印输出Java进程中线程堆栈轨迹的工具,用于生成虚拟机当前时刻的线程快照。生成的线程快照可以定位线程出现长时间停顿的原因(死锁、死循环、请求外部资源导致长时间挂起)
- jstack [options] pid
- jstack [options] executable core
- jstack [options] [server-id@] remote-hostname-or-IP
选项 | 作用 |
-F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
-l | 除堆栈外,显示关于锁的附加信息 |
-m | 如果调用到本地方法的话,可以显示C/C++的堆栈 |
7. jvisualvm
jvisualvm是JVM可视化工具,它提供了直观的用户可视化界面展示Java程序详细的信息(CPU、内存、垃圾回收等)。
8. jclasslib bytecode viewer
jclasslib是可视化Java字节码的工具,它不但可以查看Java字节码文件,同时还包含一个类库允许开发者将修改内容写入到字节码文件中。
github传送门
8. Binary Viewer
Binary Viewer是一个可以将文件以二进制、八进制、十六进制和文本格式显示的工具,通过它可以用来对Java字节码的.class文件进行二进制分析。