javap可以查看java编译器为我们生成的字节码,其使用方法可查阅帮助文档
>javap --help
用法: javap <options> <classes>
其中, 可能的选项包括:
-help --help -? 输出此用法消息
-version 版本信息
-v -verbose 输出附加信息
-l 输出行号和本地变量表
-public 仅显示公共类和成员
-protected 显示受保护的/公共类和成员
-package 显示程序包/受保护的/公共类和成员 (默认)
-p -private 显示所有类和成员
-c 对代码进行反汇编
-s 输出内部类型签名
-sysinfo 显示正在处理的类的系统信息 (路径, 大小, 日期, MD5 散列)
-constants 显示最终常量
-classpath <path> 指定查找用户类文件的位置
-cp <path> 指定查找用户类文件的位置
-bootclasspath <path> 覆盖引导类文件的位置
javap实战
源码如下:
public class test1 {
static String s = "A";
public static void main(String[] args) {
System.out.println(test());
System.out.println(s);
}
private static String test() {
try {
System.out.println("A");
return s = "A";
} finally {
System.out.println("B");
s = "B";
}
}
}
执行javap命令javap -c test1
javap -c test1
Compiled from "test1.java"
public class test1 {
static java.lang.String s;
public test1();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #3 // Method test:()Ljava/lang/String;
6: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
12: getstatic #5 // Field s:Ljava/lang/String;
15: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
static {};
Code:
0: ldc #6 // String A
2: putstatic #5 // Field s:Ljava/lang/String;
5: return
}
执行javap -c -v test1查看更多信息
javap -c -v test1
Classfile /F:/sas/Test/target/classes/test1.class
Last modified 2017-12-9; size 836 bytes
MD5 checksum 8c21be20560aefeec48520f923d513d2
Compiled from "test1.java"
public class test1
minor version: 0
major version: 50
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #9.#30 // java/lang/Object."<init>":()V
#2 = Fieldref #31.#32 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #8.#33 // test1.test:()Ljava/lang/String;
#4 = Methodref #34.#35 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Fieldref #8.#36 // test1.s:Ljava/lang/String;
#6 = String #37 // A
#7 = String #38 // B
#8 = Class #39 // test1
#9 = Class #40 // java/lang/Object
#10 = Utf8 s
#11 = Utf8 Ljava/lang/String;
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 LocalVariableTable
#17 = Utf8 this
#18 = Utf8 Ltest1;
#19 = Utf8 main
#20 = Utf8 ([Ljava/lang/String;)V
#21 = Utf8 args
#22 = Utf8 [Ljava/lang/String;
#23 = Utf8 test
#24 = Utf8 ()Ljava/lang/String;
#25 = Utf8 StackMapTable
#26 = Class #41 // java/lang/Throwable
#27 = Utf8 <clinit>
#28 = Utf8 SourceFile
#29 = Utf8 test1.java
#30 = NameAndType #12:#13 // "<init>":()V
#31 = Class #42 // java/lang/System
#32 = NameAndType #43:#44 // out:Ljava/io/PrintStream;
#33 = NameAndType #23:#24 // test:()Ljava/lang/String;
#34 = Class #45 // java/io/PrintStream
#35 = NameAndType #46:#47 // println:(Ljava/lang/String;)V
#36 = NameAndType #10:#11 // s:Ljava/lang/String;
#37 = Utf8 A
#38 = Utf8 B
#39 = Utf8 test1
#40 = Utf8 java/lang/Object
#41 = Utf8 java/lang/Throwable
#42 = Utf8 java/lang/System
#43 = Utf8 out
#44 = Utf8 Ljava/io/PrintStream;
#45 = Utf8 java/io/PrintStream
#46 = Utf8 println
#47 = Utf8 (Ljava/lang/String;)V
{
static java.lang.String s;
descriptor: Ljava/lang/String;
flags: ACC_STATIC
public test1();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 2: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ltest1;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #3 // Method test:()Ljava/lang/String;
6: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
12: getstatic #5 // Field s:Ljava/lang/String;
15: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
LineNumberTable:
line 6: 0
line 7: 9
line 8: 18
LocalVariableTable:
Start Length Slot Name Signature
0 19 0 args [Ljava/lang/String;
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: ldc #6 // String A
2: putstatic #5 // Field s:Ljava/lang/String;
5: return
LineNumberTable:
line 3: 0
}
SourceFile: "test1.java"
其中栈和局部变量操作参见 Java虚拟机--字节码指令集
查阅资料
Java中return与finally的执行顺序分析(根据字节码分析)
javap 学习日记
Java finally语句到底是在return之前还是之后执行?
finally执行顺序面试题