class文件结构:
CA FE BA BE 00 00 00 34 00 25 0A 00 09 00 14 09
00 15 00 16 08 00 17 0A 00 18 00 19 08 00 1A 08
00 1B 08 00 1C 07 00 1D 07 00 1E 01 00 06 3C 69
6E 69 74 3E 01 00 03 28 29 56 01 00 04 43 6F 64
65 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61
62 6C 65 01 00 04 6D 61 69 6E 01 00 16 28 5B 4C
6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67
3B 29 56 01 00 03 66 6F 6F 01 00 0D 53 74 61 63
6B 4D 61 70 54 61 62 6C 65 01 00 0A 53 6F 75 72
63 65 46 69 6C 65 01 00 0F 48 65 6C 6C 6F 57 6F
72 6C 64 2E 6A 61 76 61 0C 00 0A 00 0B 07 00 1F
0C 00 20 00 21 01 00 0F 68 65 6C 6C 6F 20 77 6F
72 6C 64 20 21 21 21 07 00 22 0C 00 23 00 24 01
00 02 23 30 01 00 02 23 31 01 00 07 64 65 66 61
75 6C 74 01 00 17 63 6F 6D 2F 73 75 6E 2F 74 65
73 74 2F 48 65 6C 6C 6F 57 6F 72 6C 64 01 00 10
6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74
01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 53 79 73
74 65 6D 01 00 03 6F 75 74 01 00 15 4C 6A 61 76
61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D
3B 01 00 13 6A 61 76 61 2F 69 6F 2F 50 72 69 6E
74 53 74 72 65 61 6D 01 00 07 70 72 69 6E 74 6C
6E 01 00 15 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F
53 74 72 69 6E 67 3B 29 56 00 21 00 08 00 09 00
00 00 00 00 03 00 01 00 0A 00 0B 00 01 00 0C 00
00 00 1D 00 01 00 01 00 00 00 05 2A B7 00 01 B1
00 00 00 01 00 0D 00 00 00 06 00 01 00 00 00 09
00 09 00 0E 00 0F 00 01 00 0C 00 00 00 25 00 02
00 01 00 00 00 09 B2 00 02 12 03 B6 00 04 B1 00
00 00 01 00 0D 00 00 00 0A 00 02 00 00 00 0B 00
08 00 0C 00 09 00 10 00 0B 00 01 00 0C 00 00 00
7E 00 02 00 01 00 00 00 3B 03 3B 1A AB 00 00 00
2F 00 00 00 02 00 00 00 00 00 00 00 19 00 00 00
01 00 00 00 24 B2 00 02 12 05 B6 00 04 A7 00 16
B2 00 02 12 06 B6 00 04 A7 00 0B B2 00 02 12 07
B6 00 04 B1 00 00 00 02 00 0D 00 00 00 22 00 08
00 00 00 0E 00 02 00 0F 00 1C 00 11 00 24 00 12
00 27 00 14 00 2F 00 15 00 32 00 17 00 3A 00 1A
00 11 00 00 00 09 00 04 FC 00 1C 01 0A 0A 07 00
01 00 12 00 00 00 02 00 13
上边展示的是十六位进制字符串。
一个字节表示8位二进制数,一个十六进制字符代表4位二进制数,
一个字节两个十六进制字符
Class文件结构如下:
1.魔数(前4个字节 CA FE BA BE )
2.次版本号(第5个和第6个字节)
3.主版本号(第7个和第8个字节)
4.常量池(因为常量池数量不固定 用2个字节表示长度)(常量第一个字节是tag标识常量类型)
5.访问标志
6.类索引、父类索引和接口索引集合。
7.字段集合
8.方法集合
9.属性表集合(Code属性)
Code属性存储的是java程序方法体里面代码经过javac编译器处理之后的字节码指令。
这区域规定了局部变量表所需的存储空间(max_stack),操作数栈的深度最大值(max_stack)等等。jvm运行时根据这个值分配栈帧中操作栈深度。
魔数:说白了通过魔数识别文件类型
class文件:前4个字节 CA FE BA BE 表示JVM能够识别的Class文件。
png图片:89 50 4E 47 表示.PNG(大家可以验证一下)
次版本号:第5个和第6个字节表示 00 00(JDK12之前全部为0,JDK12副本号启动标识
技术预览版 必须将次版本号标识为65535 JVM加载的是才能区分)
主版本号:第7个和第8个字节表示 00 34(十六进制转换为十进制 52表示JDK1.8版本编译的文件)
常量池数量:因为常量池数量不固定 用2个字节表示 00 25(十六进制转换为十进制 25表示37个) 但是表示36个常量。常量池下标是从1开始,区别于其他的集合类型(接口索引,字段表,方法表,属性表等)。
常量池主要存放:字面量和符号引用。
字面量:文本字符串和被声明final的常量值等:
符号引用:被模块导出或者开发的包,类和接口的权限定名,字段的名称和描述,
方法的名称和描述,方法句柄和方法类型,动态调用点和动态常量。
常量池的项目类型
常量池中数据类型结构
常量池第一个常量:0A(十六进制转换为十进制 0A表示10) 查询常量池类型表,类中方法的符号引用。(CONSTANT_Methodref_info)
指向类或接口符合引用: CONSTANT_Class_info 00 09(十六进制转换为十进制 0A表示9)
字段或方法的部分符合引用:CONSTANT_NameAndType_info 00 14(十六进制转换为十进制 14表示20)
验证一下:
常量池第二个常量:09(十六进制转换为十进制 0A表示09)查询常量池类型表,字段的符号引用(CONSTANT_Filedref_info )
指向类或接口符合引用: CONSTANT_Class_info 00 15(十六进制转换为十进制 15表示21)
字段或方法的部分符合引用:CONSTANT_NameAndType_info 00 16(十六进制转换为十进制 16表示22)
验证一下:
在这里就不一个个翻译了。
javap -verbose HelloWorld.class 命令输出文件字节内容。
源码
package com.sun.test;
/**
* @program:javac-source-code-reading
* @description:
* @create:2020-05-25 11:18
**/
public class HelloWorld {
public static void main(String[] args) {
System.out.println("hello world !!!");
}
public static void foo() {
int a = 0;
switch (a) {
case 0:
System.out.println("#0");
break;
case 1:
System.out.println("#1");
break;
default:
System.out.println("default");
break;
}
}
}