引入
之前已经讲述了如何在 windows 环境通过 命令行的方式编译Java 代码。
此篇文章作为JVM 系列的引入,简要的说明如何在 windows 平台进行 Java 编译后的 class 文件的查看。其实 JDK 中已经内置了这些工具。可以在%JAVA_HOME%\bin
目录下看到javap.exe
这个可执行文件。一些其他的工具在该目录下也都能看到,不过不是此处重点,还是言归正传。本文只做基本演示,后面详细介绍字节码时会逐行详细分析。
示例代码
此处就举一个最简单不过的 Java 示例程序,代码如下:
publicclassTest{privateintm;publicintinc(){returnm+1;}}
利器 javap
进入命令行,编译完源码后,会看到源码文件旁有个同名的.class
文件。接着执行如下命令
javap-cTest(或javap-cTest.class)
可以看到如下结果:
F:\tmp\jvmTmp>javap-cTestCompiledfrom"Test.java"publicclassTest{publicTest();Code:0:aload_01:invokespecial#1//Methodjava/lang/Object."<init>":()V4:returnpublicintinc();Code:0:aload_01:getfield#2//Fieldm:I4:iconst_15:iadd6:ireturn}
这只是展示了当前类和方法的信息。如果要查看详细内容包括常量池、行号表、异常表等信息,可以通过如下命令查看:
javap-verboseTest
执行命令结果如下:
F:\tmp\jvmTmp>javap-verboseTestClassfile/F:/tmp/jvmTmp/Test.classLastmodified-7-18;size265bytesMD5checksum0d5efc4b65ae7eb6d64f84136ce58ff9Compiledfrom"Test.java"publicclassTestminorversion:0majorversion:52flags:ACC_PUBLIC,ACC_SUPERConstantpool:#1=Methodref#4.#15//java/lang/Object."<init>":()V#2=Fieldref#3.#16//Test.m:I#3=Class#17//Test#4=Class#18//java/lang/Object#5=Utf8m#6=Utf8I#7=Utf8<init>#8=Utf8()V#9=Utf8Code#10=Utf8LineNumberTable#11=Utf8inc#12=Utf8()I#13=Utf8SourceFile#14=Utf8Test.java#15=NameAndType#7:#8//"<init>":()V#16=NameAndType#5:#6//m:I#17=Utf8Test#18=Utf8java/lang/Object{publicTest();descriptor:()Vflags:ACC_PUBLICCode:stack=1,locals=1,args_size=10:aload_01:invokespecial#1//Methodjava/lang/Object."<init>":()V4:returnLineNumberTable:line1:0publicintinc();descriptor:()Iflags:ACC_PUBLICCode:stack=2,locals=1,args_size=10:aload_01:getfield#2//Fieldm:I4:iconst_15:iadd6:ireturnLineNumberTable:line6:0}SourceFile:"Test.java"
可以看到多了文件路径、文件校验、上次修改时间、大小、版本信息、常量池等信息。这是展示字节码信息最丰富的命令了。class
文件中的信息几乎都展示出来了。其中第 11 行可以看到Constant pool
就是常量池的意思,即行号 12 到 29 都是常量池部分。常量池中的常量通常以#
开头接上序号。
#3=Class#17//Test
如上所示就是第三个常量,=
号后面是该常量项的类型,后面#17
,表示指向第 17 个常量,这里不做展开。
更多用法
当然,javap
的用法不知这些,可以通过如下命令查看所有用法:
F:\tmp\jvmTmp>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>覆盖引导类文件的位置
大家可以都尝试下,加深印象。