Class类文件的结构
Class文件是一组以8个字节为基础单位的二进制流,各数据严格按照顺序紧凑排列在文件中
Class文件采用一种伪结构来存储数据,伪结构中只有两种数据类型
- 无符号数:基本数据类型,以u1/u2/u4/u8分别代表1/2/4/8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或UTF-8字符串
- 表:多个无符号数或其他表作为数据项构成的复合数据类型,所有表的命名以“_info”结尾,用于描述有层次关系的符合结构的数据,整个Class文件本质上也是一张表,整张表由以下几个部分严格按顺序组成
![image-20221025174343354](/i/l/?n=23&i=blog/1441158/202307/1441158-20230724173119835-400563653.png)
常量池
常量池的项目类型
![image-20221025161723681](/i/l/?n=23&i=blog/1441158/202307/1441158-20230724173120324-393636900.png)
以上全部使用的16进制
HelloWorld程序的javap呈现结果
Classfile /Users/lichang/IdeaProjects/learnJava/src/javaVirtual/HelloWorld.class
Last modified 2022-10-21; size 609 bytes
MD5 checksum 9f6a98edd2845904eb28a20677f736bb
Compiled from "HelloWorld.java"
public class javaVirtual.HelloWorld
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #11.#20 // java/lang/Object."<init>":()V
#2 = String #21 // cc
#3 = Fieldref #22.#23 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Class #24 // java/lang/StringBuilder
#5 = Methodref #4.#20 // java/lang/StringBuilder."<init>":()V
#6 = String #25 // hello
#7 = Methodref #4.#26 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#8 = Methodref #4.#27 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#9 = Methodref #28.#29 // java/io/PrintStream.println:(Ljava/lang/String;)V
#10 = Class #30 // javaVirtual/HelloWorld
#11 = Class #31 // java/lang/Object
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 main
#17 = Utf8 ([Ljava/lang/String;)V
#18 = Utf8 SourceFile
#19 = Utf8 HelloWorld.java
#20 = NameAndType #12:#13 // "<init>":()V
#21 = Utf8 cc
#22 = Class #32 // java/lang/System
#23 = NameAndType #33:#34 // out:Ljava/io/PrintStream;
#24 = Utf8 java/lang/StringBuilder
#25 = Utf8 hello
#26 = NameAndType #35:#36 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#27 = NameAndType #37:#38 // toString:()Ljava/lang/String;
#28 = Class #39 // java/io/PrintStream
#29 = NameAndType #40:#41 // println:(Ljava/lang/String;)V
#30 = Utf8 javaVirtual/HelloWorld
#31 = Utf8 java/lang/Object
#32 = Utf8 java/lang/System
#33 = Utf8 out
#34 = Utf8 Ljava/io/PrintStream;
#35 = Utf8 append
#36 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#37 = Utf8 toString
#38 = Utf8 ()Ljava/lang/String;
#39 = Utf8 java/io/PrintStream
#40 = Utf8 println
#41 = Utf8 (Ljava/lang/String;)V
{
public javaVirtual.HelloWorld();
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 3: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: ldc #2 // String cc
2: astore_1
3: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: ldc #6 // String hello
15: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: aload_1
19: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: return
LineNumberTable:
line 5: 0
line 6: 3
line 7: 28
}
SourceFile: "HelloWorld.java"
二进制
cafe babe 0000 0034 002a 0a00 0b00 1408
0015 0900 1600 1707 0018 0a00 0400 1408
0019 0a00 0400 1a0a 0004 001b 0a00 1c00
1d07 001e 0700 1f01 0006 3c69 6e69 743e
0100 0328 2956 0100 0443 6f64 6501 000f
4c69 6e65 4e75 6d62 6572 5461 626c 6501
0004 6d61 696e 0100 1628 5b4c 6a61 7661
2f6c 616e 672f 5374 7269 6e67 3b29 5601
000a 536f 7572 6365 4669 6c65 0100 0f48
656c 6c6f 576f 726c 642e 6a61 7661 0c00
0c00 0d01 0002 6363 0700 200c 0021 0022
0100 176a 6176 612f 6c61 6e67 2f53 7472
696e 6742 7569 6c64 6572 0100 0668 656c
6c6f 200c 0023 0024 0c00 2500 2607 0027
0c00 2800 2901 0016 6a61 7661 5669 7274
7561 6c2f 4865 6c6c 6f57 6f72 6c64 0100
106a 6176 612f 6c61 6e67 2f4f 626a 6563
7401 0010 6a61 7661 2f6c 616e 672f 5379
7374 656d 0100 036f 7574 0100 154c 6a61
7661 2f69 6f2f 5072 696e 7453 7472 6561
6d3b 0100 0661 7070 656e 6401 002d 284c
6a61 7661 2f6c 616e 672f 5374 7269 6e67
3b29 4c6a 6176 612f 6c61 6e67 2f53 7472
696e 6742 7569 6c64 6572 3b01 0008 746f
5374 7269 6e67 0100 1428 294c 6a61 7661
2f6c 616e 672f 5374 7269 6e67 3b01 0013
6a61 7661 2f69 6f2f 5072 696e 7453 7472
6561 6d01 0007 7072 696e 746c 6e01 0015
284c 6a61 7661 2f6c 616e 672f 5374 7269
6e67 3b29 5600 2100 0a00 0b00 0000 0000
0200 0100 0c00 0d00 0100 0e00 0000 1d00
0100 0100 0000 052a b700 01b1 0000 0001
000f 0000 0006 0001 0000 0003 0009 0010
0011 0001 000e 0000 003d 0003 0002 0000
001d 1202 4cb2 0003 bb00 0459 b700 0512
06b6 0007 2bb6 0007 b600 08b6 0009 b100
0000 0100 0f00 0000 0e00 0300 0000 0500
0300 0600 1c00 0700 0100 1200 0000 0200
13
0100 0328 2956 0100 0443 6f64 6501 000f
03282956为()V表示空参构造器
01表示UTF-8字符串
访问标识与继承信息
常量池接受后,紧接着2个字节表示访问标志(access_flags)
访问标志表
![image-20221025165805955](/i/l/?n=23&i=blog/1441158/202307/1441158-20230724173120756-1934207759.png)