Skip to content

类文件结构

类文件结构

  • ==class 文件构成:无符号数 + 表==
    • 无符号数:用 un 表示,是 class 文件中的基本数据类型
      • u1 表示 1个字节、u2 表示 2个字节、u4 表示 4个字节、u8 表示 8个字节
      • 可以表示数字、索引引用、数量值、字符串等
    • 表:用 _info 标识,由无符号数或者表 组成的复合数据类型

将一个 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个字节

image-20230511125943796

字段名称字段类型字段长度描述
magic numberu44字节魔数,固定值0xCAFEBABE
minor_versionu22字节次版本号
major_versionu22字节主版本号
constant_pool_countu22字节常量池计数
constant_pool==cp_info[ ]==变长常量池表
access_flagsu22字节类访问标志
this_classu22字节类索引
super_classu22字节父类索引
interfaces_countu22字节接口计数
interfaces==u2[ ]==变长接口表
fields_countu22字节字段计数
fields==field_info[ ]==变长字段表
methods_countu22字节方法计数
methods==method_info[ ]==变长方法表
attributes_countu22字节属性计数
attributes==attribute_info[ ]==变长属性表

魔数(magic number)

魔数

百度百科 - 魔数

魔数 magic number:在文件的二进制最前面,一组固定的数字,通常用于识别文件格式,数据类型等信息。在计算机安全中,魔数常用于检测和防止恶意文件的执行。

不会因为你修改文件的后缀名而改变,所以将 xxx.jpeg 修改成 xxx.png 在某些严格校验的时候,并没有用。

文件类型魔数(十六进制)
JPEG0xFF D8 FF
PNG0x89 50 4E 47 0D 0A 1A 0A
GIF0x47 49 46 38
PDF0x25 50 44 46
ZIP0x50 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.1J2SE 1.2J2SE 1.3J2SE 1.4J2SE 5.0JDK 6JDK 7JDK 8JDK 9JDK 10JDK 11JDK 12JDK 13JDK 14JDK 15JDK 16JDK 17
主版本号==45==46474849505152535455565758596061

常量池

常量池计数(constant_pool_count)

  • ==容器计数从1开始==,比如 constant_pool_count = 20,说明 constant_pool(常量池表) 有19 个常量
  • ==第 0 项常量池是 JVM 中的保留项,它不存储任何数据==,只是为了保留第 1 个常量池的索引值为 1,这样在 JVM 访问常量池时,如果返回索引值 0,就表示没有找到任何数据。

常量池表(constant_pool)

访问标志

类索引、父类索引、接口索引

字段表

方法表

属性表