上QQ阅读APP看书,第一时间看更新
1.3 使用javap查看类文件
前面零星介绍了使用javap来查看类文件,本节将详细介绍javap命令。由前面的小节也可以看出class文件是二进制块,想直接与它打交道比较艰难,好在JDK提供了专门用来分析类文件的工具javap以窥探class文件内部的细节。它的使用方式如下:
javap [options] <classes>
不加任何参数运行javap的输出如下所示。
javap HelloWorld Compiled from "HelloWorld.java" public class HelloWorld { public HelloWorld(); public static void main(java.lang.String[]); }
默认情况下,javap会显示访问权限为public、protected和默认级别的方法。如果想要显示private方法和字段,就需要加上 -p选项。
javap还有一个好用的选项 -s,可以输出类型描述符签名信息,HelloWorld.java所有的方法签名如下所示。
javap -s HelloWorld Compiled from "HelloWorld.java" public class HelloWorld { public HelloWorld(); descriptor: ()V public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String; )V }
加上 -c选项可以对类文件进行反编译,可以显示出方法内的字节码,加上 -c选项以后的输出如下所示。
javap -c HelloWorld public static void main(java.lang.String[]); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String hello, world 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/ String; )V 8: return
加上 -v选项可以显示更加详细的内容,比如版本号、类访问权限、常量池相关的信息,是一个非常有用的参数,如下所示。
javap -v HelloWorld public class HelloWorld minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #6.#15 // java/lang/Object."<init>":()V #2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream; ...
还有一个比较少用的 -l选项,可以用来显示行号表和局部变量表,实测并没有输出局部变量表,只显示了行号表,如下所示。
javap -l HelloWorld public static void main(java.lang.String[]); LineNumberTable: line 3: 0 line 4: 8
原因是要想显示局部变量表,需要在javac编译的时候加 -g选项,生成所有的调试信息选项,加上 -g选项编译javac -g HelloWorld.java以后重新执行javap -l命令就可以看到局部变量表(LocalVariableTable)了,如下所示。
javap -l HelloWorld public static void main(java.lang.String[]); LineNumberTable: line 3: 0 line 4: 8 LocalVariableTable: Start Length Slot Name Signature 0 9 0 args [Ljava/lang/String;