类文件结构
类文件结构
- ==class 文件构成:无符号数 + 表==
- 无符号数:用 un 表示,是 class 文件中的基本数据类型
- u1 表示 1个字节、u2 表示 2个字节、u4 表示 4个字节、u8 表示 8个字节
- 可以表示数字、索引引用、数量值、字符串等
- 表:用 _info 标识,由无符号数或者表 组成的复合数据类型
- 无符号数:用 un 表示,是 class 文件中的基本数据类型
将一个 class 文件用 16 进制展示,如下:
CA FE BA BE 00 00 00 34 00 23 0A 00 09 00 1C 09 …..
2位十六进制 = 1个字节
CA FE BA BE 就是 4个字节
字段名称 | 字段类型 | 字段长度 | 描述 |
---|---|---|---|
magic number | u4 | 4字节 | 魔数,固定值0xCAFEBABE |
minor_version | u2 | 2字节 | 次版本号 |
major_version | u2 | 2字节 | 主版本号 |
constant_pool_count | u2 | 2字节 | 常量池计数 |
constant_pool | ==cp_info[ ]== | 变长 | 常量池表 |
access_flags | u2 | 2字节 | 类访问标志 |
this_class | u2 | 2字节 | 类索引 |
super_class | u2 | 2字节 | 父类索引 |
interfaces_count | u2 | 2字节 | 接口计数 |
interfaces | ==u2[ ]== | 变长 | 接口表 |
fields_count | u2 | 2字节 | 字段计数 |
fields | ==field_info[ ]== | 变长 | 字段表 |
methods_count | u2 | 2字节 | 方法计数 |
methods | ==method_info[ ]== | 变长 | 方法表 |
attributes_count | u2 | 2字节 | 属性计数 |
attributes | ==attribute_info[ ]== | 变长 | 属性表 |
魔数(magic number)
魔数
魔数 magic number:在文件的二进制最前面,一组固定的数字,通常用于识别文件格式,数据类型等信息。在计算机安全中,魔数常用于检测和防止恶意文件的执行。
不会因为你修改文件的后缀名而改变,所以将 xxx.jpeg 修改成 xxx.png 在某些严格校验的时候,并没有用。
文件类型 | 魔数(十六进制) |
---|---|
JPEG | 0xFF D8 FF |
PNG | 0x89 50 4E 47 0D 0A 1A 0A |
GIF | 0x47 49 46 38 |
0x25 50 44 46 | |
ZIP | 0x50 4B 03 04 |
==class文件== | ==0xCAFEBABE== |
class 魔数
.java 文件编译之后的 .class 文件,前 4 个字节,值为 ==0xCAFEBABE==,表示该文件是符合 JVM 规范的二进制文件。
当 JVM 加载一个 .class 文件,首先读取文件中的魔数进行判断,如果魔数不匹配 JVM 不会将其加载到内存。
CAFE BABE (咖啡宝贝):在 Oak 时期就已经确定。 James Gosling 在开发 Java 时,想给 Java 的字节码文件加入一些有趣的东西,于是他以魔法棒(Magic Wand)为灵感,将魔法棒的十六进制表示(0xCAFEBABE)作为 Java 字节码文件的魔数
版本号
次版本号(minor_version)
主版本号(major_version)
JVM Class 文件版本号是由两个==无符号短整型==(16 位)来表示,分别是 minor_version 和 major_version。其中,minor_version 表示次版本号,major_version 表示主版本号。
==JDK 1.1 版本号从 45 开始,每个大版本向上加1==,高版本向下兼容。
JVM 版本 | JDK 1.1 | J2SE 1.2 | J2SE 1.3 | J2SE 1.4 | J2SE 5.0 | JDK 6 | JDK 7 | JDK 8 | JDK 9 | JDK 10 | JDK 11 | JDK 12 | JDK 13 | JDK 14 | JDK 15 | JDK 16 | JDK 17 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
主版本号 | ==45== | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
常量池
常量池计数(constant_pool_count)
- ==容器计数从1开始==,比如 constant_pool_count = 20,说明 constant_pool(常量池表) 有19 个常量
- ==第 0 项常量池是 JVM 中的保留项,它不存储任何数据==,只是为了保留第 1 个常量池的索引值为 1,这样在 JVM 访问常量池时,如果返回索引值 0,就表示没有找到任何数据。