其他
走进字节码之查看工具
引入
之前已经讲述了如何在 windows 环境通过 命令行的方式编译Java 代码。
此篇文章作为JVM 系列的引入,简要的说明如何在 windows 平台进行 Java 编译后的 class 文件的查看。其实 JDK 中已经内置了这些工具。可以在 %JAVA_HOME%\bin
目录下看到 javap.exe
这个可执行文件。一些其他的工具在该目录下也都能看到。本文只做基本演示,后面详细介绍字节码时会逐行详细分析。
示例代码
此处就举一个最简单不过的 Java 示例程序,代码如下:
1public class Test{
2
3 private int m;
4
5 public int inc(){
6 return m + 1;
7 }
8
9}
利器 javap
进入命令行,编译完源码后,会看到源码文件旁有个同名的 .class
文件。接着执行如下命令
1javap -c Test (或 javap -c Test.class)
可以看到如下结果:
1F:\tmp\jvmTmp>javap -c Test
2
3Compiled from "Test.java"
4public class Test {
5 public Test();
6 Code:
7 0: aload_0
8 1: invokespecial
9 4: return
10
11 public int inc();
12 Code:
13 0: aload_0
14 1: getfield
15 4: iconst_1
16 5: iadd
17 6: ireturn
18}
这只是展示了当前类和方法的信息。如果要查看详细内容包括常量池、行号表、异常表等信息,可以通过如下命令查看:
1javap -verbose Test
执行命令结果如下:
1F:\tmp\jvmTmp>javap -verbose Test
2
3Classfile /F:/tmp/jvmTmp/Test.class
4 Last modified 2018-7-18; size 265 bytes
5 MD5 checksum 0d5efc4b65ae7eb6d64f84136ce58ff9
6 Compiled from "Test.java"
7public class Test
8 minor version: 0
9 major version: 52
10 flags: ACC_PUBLIC, ACC_SUPER
11Constant pool:
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30{
31 public Test();
32 descriptor: ()V
33 flags: ACC_PUBLIC
34 Code:
35 stack=1, locals=1, args_size=1
36 0: aload_0
37 1: invokespecial
38 4: return
39 LineNumberTable:
40 line 1: 0
41
42 public int inc();
43 descriptor: ()I
44 flags: ACC_PUBLIC
45 Code:
46 stack=2, locals=1, args_size=1
47 0: aload_0
48 1: getfield
49 4: iconst_1
50 5: iadd
51 6: ireturn
52 LineNumberTable:
53 line 6: 0
54}
55SourceFile: "Test.java"
可以看到多了文件路径、文件校验、上次修改时间、大小、版本信息、常量池等信息。这是展示字节码信息最丰富的命令了。class
文件中的信息几乎都展示出来了。其中第 11 行可以看到 Constant pool
就是常量池的意思,即行号 12 到 29 都是常量池部分。常量池中的常量通常以 #
开头接上序号。
1#3 = Class #17 // Test
如上所示就是第三个常量,=
号后面是该常量项的类型,后面 #17
,表示指向第 17 个常量,这里不做展开。
更多用法
当然,javap
的用法不知这些,可以通过如下命令查看所有用法:
1F:\tmp\jvmTmp>javap -help
2
3用法: javap <options> <classes>
4其中, 可能的选项包括:
5 -help --help -? 输出此用法消息
6 -version 版本信息
7 -v -verbose 输出附加信息
8 -l 输出行号和本地变量表
9 -public 仅显示公共类和成员
10 -protected 显示受保护的/公共类和成员
11 -package 显示程序包/受保护的/公共类
12 和成员 (默认)
13 -p -private 显示所有类和成员
14 -c 对代码进行反汇编
15 -s 输出内部类型签名
16 -sysinfo 显示正在处理的类的
17 系统信息 (路径, 大小, 日期, MD5 散列)
18 -constants 显示最终常量
19 -classpath <path> 指定查找用户类文件的位置
20 -cp <path> 指定查找用户类文件的位置
21 -bootclasspath <path> 覆盖引导类文件的位置
大家可以都尝试下,加深印象。