版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_44082567/article/details/86081531
Class文件是经过JDK中javac工具编译后的一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符.
如何查看编译后的Class文件?推荐两种不需要安装任何额外工具的查看方式.在IDE中打开.class文件,会被内置的反编译插件反编译,还原成java类文件,既不能起到查看.class文件的目的,也不符合不安装额外工具的要求.
使用javap工具
- 对于任意的类,首先使用javac工具进行编译
javac HelloWorld.java
- 使用JDK中的javap工具打开.class文件
javap -verbose HelloWorld.class
即可得到相应的.class文件内容
Classfile /E:/学习及反思/HelloWorld.class
Last modified 2019-1-8; size 426 bytes
MD5 checksum dfd16ec7464dcda9bfc32d22988a5a82
Compiled from "HelloWorld.java"
public class HelloWorld
SourceFile: "HelloWorld.java"
minor version: 0
major version: 51
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;
#3 = String #18 // Hello World!
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // HelloWorld
#6 = Class #22 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 SourceFile
#14 = Utf8 HelloWorld.java
#15 = NameAndType #7:#8 // "<init>":()V
#16 = Class #23 // java/lang/System
#17 = NameAndType #24:#25 // out:Ljava/io/PrintStream;
#18 = Utf8 Hello World!
#19 = Class #26 // java/io/PrintStream
#20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V
#21 = Utf8 HelloWorld
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/System
#24 = Utf8 out
#25 = Utf8 Ljava/io/PrintStream;
#26 = Utf8 java/io/PrintStream
#27 = Utf8 println
#28 = Utf8 (Ljava/lang/String;)V
{
public HelloWorld();
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 1: 0
public static void main(java.lang.String[]);
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: ldc #3 // String Hello World!
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 3: 0
line 4: 8
}
使用命令行窗口
- 首先编译任意.java类文件
javac HelloWorld.java
- 使用命令行窗口查看.class文件,这时打开的文件为2进制显示
vim HelloWorld.class
一坨乱码 like a shit!
Êþ º ¾ ^@^@^@3^@^]
^@^F^@^O ^@^P^@^Q^H^@^R
^@^S^@^T^G^@^U^G^@^V^A^@^F<init>^A^@^C()V^A^@^DCode^A^@^OLineNumberTable^A^@^Dmain^A^@^V([Ljava/lang/String;)V^A^@
SourceFile^A^@^OHelloWorld.java^L^@^G^@^H^G^@^W^L^@^X^@^Y^A^@^LHello World!^G^@^Z^L^@^[^@^\^A^@
HelloWorld^A^@^Pjava/lang/Object^A^@^Pjava/lang/System^A^@^Cout^A^@^ULjava/io/PrintStream;^A^@^Sjava/io/PrintStream^A^@^Gprintln^A^@^U(Ljava/lang/String;)V^@!^@^E^@^F^@^@^@^@^@^B^@^A^@^G^@^H^@^A^@ ^@^@^@^]^@^A^@^A^@^@^@^E*·^@^A±^@^@^@^A^@
^@^@^@^F^@^A^@^@^@^A^@ ^@^K^@^L^@^A^@ ^@^@^@%^@^B^@^A^@^@^@ ² ^@^B^R^C¶ ^@^D±^@^@^@^A^@
^@^@^@
^@^B^@^@^@^C^@^H^@^D^@^A^@^M^@^@^@^B^@^N
- 使用命令
:%!xxd
,即可转变为16进制显示
截取部分
00000000: cafe babe 0000 0033 001d 0a00 0600 0f09 .......3........
00000010: 0010 0011 0800 120a 0013 0014 0700 1507 ................
00000020: 0016 0100 063c 696e 6974 3e01 0003 2829 .....<init>...()
00000030: 5601 0004 436f 6465 0100 0f4c 696e 654e V...Code...LineN
00000040: 756d 6265 7254 6162 6c65 0100 046d 6169 umberTable...mai
00000050: 6e01 0016 285b 4c6a 6176 612f 6c61 6e67 n...([Ljava/lang
00000060: 2f53 7472 696e 673b 2956 0100 0a53 6f75 /String;)V...Sou
00000070: 7263 6546 696c 6501 000f 4865 6c6c 6f57 rceFile...HelloW
00000080: 6f72 6c64 2e6a 6176 610c 0007 0008 0700 orld.java.......
00000090: 170c 0018 0019 0100 0c48 656c 6c6f 2057 .........Hello W
000000a0: 6f72 6c64 2107 001a 0c00 1b00 1c01 000a orld!...........
000000b0: 4865 6c6c 6f57 6f72 6c64 0100 106a 6176 HelloWorld...jav
000000c0: 612f 6c61 6e67 2f4f 626a 6563 7401 0010 a/lang/Object...
000000d0: 6a61 7661 2f6c 616e 672f 5379 7374 656d java/lang/System
000000e0: 0100 036f 7574 0100 154c 6a61 7661 2f69 ...out...Ljava/i
000000f0: 6f2f 5072 696e 7453 7472 6561 6d3b 0100 o/PrintStream;..
00000100: 136a 6176 612f 696f 2f50 7269 6e74 5374 .java/io/PrintSt
00000110: 7265 616d 0100 0770 7269 6e74 6c6e 0100 ream...println..
00000120: 1528 4c6a 6176 612f 6c61 6e67 2f53 7472 .(Ljava/lang/Str
00000130: 696e 673b 2956 0021 0005 0006 0000 0000 ing;)V.!........
00000140: 0002 0001 0007 0008 0001 0009 0000 001d ................
00000150: 0001 0001 0000 0005 2ab7 0001 b100 0000 ........*.......
00000160: 0100 0a00 0000 0600 0100 0000 0100 0900 ................
00000170: 0b00 0c00 0100 0900 0000 2500 0200 0100 ..........%.....
00000180: 0000 09b2 0002 1203 b600 04b1 0000 0001 ................
00000190: 000a 0000 000a 0002 0000 0003 0008 0004 ................
每个Class文件的头四个字节称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接收的Class文件.而java的Class文件的魔数是非常有情怀的,值为0xCAFEBABE,也就是java的标志.