JVM - 和CAFEBABE相关的那些知识

【投稿赢 iPhone 17】「我的第一个开源项目」故事征集:用代码换C位出道! 10w+人浏览 1.7k人参与

Long long ago,在小编刚步入职场时,做了一个练手的小工具,能够展示一个图片及其相关的描述信息,并将所有信息保存在一个文件中,支持读取、修改操作,各位看官是不是立马就有实现思路了(如果没有思路,不妨停一下自己想想)。在写这篇文章时,不由的想起这个小工具,这个小工具实现思路和Class文件结构实现方式不能说完全一样,只能说一模一样。

总览

前面说过,Class文件是字节码的载体,而字节码(中间代码)是java语言无关平台的统一表示(诞生篇骨架篇)。我们说Class文件结构,其实主要是说,字节码在Class文件中要如何表示。根据《Java虚拟机规范》规定,Class文件格式采用一种类似于C语言结构体的一种伪结构来存储数据,这种结构只有两种数据类型:无符号数

无符号数:属于基本数据类型,用于表示数字、索引引用或按照UTF-8编码的字符串值;以u1、u2、u4、u8分别代表1个字节、2个字节、4个字节、8个字节的无符号数;
:由多个无符号数或者其他表作为数据项构成的复合数据类型;便于区分,所有表都习惯以"_info"结尾;

整个Class文件也可以视为一张大表,其结构严格按照下表顺序定义,各个部分之间没有任何分割符。

类型 名称 数量 说明
u4 magic 1 魔数,固定为0xCAFEBABE
u2 minor_version 1 次版本号
u2 major_version 1 主版本号 (Java 8=52, 11=55, 17=61, 21=65)
u2 constant_pool_count 1 常量池大小 + 1
cp_info constant_pool constant_pool_count - 1 常量池,类的资源仓库
u2 access_flags 1 类/接口的访问标志 (public, final…)
u2 this_class 1 当前类在常量池的索引
u2 super_class 1 父类在常量池的索引 (Object为0)
u2 interfaces_count 1 实现的接口数量
u2 interfaces interfaces_count 接口在常量池的索引集合
u2 fields_count 1 字段表数量
field_info fields fields_count 字段表,描述所有字段
u2 methods_count 1 方法表数量
method_info methods methods_count 方法表,描述所有方法
u2 attributes_count 1 属性表数量
attribute_info attributes attributes_count 属性表,附加信息

真实的Class文件使用16进制工具打开后如下图所示,除了"CAFEBABE"之外,其他就完全不知道说啥,我们也完全没兴趣去一个个字节去翻译。来吧,上工具。。。
16进制工具解析的文件
如下是经过jclasslib解析后的class文件结构,这就非常清晰了:
使用jclasslib解析后的文件结构

建议此处停顿下,将jclasslib解析的class结构信息和上述Class文件结构图一一对应看一下。

类型说明

魔数:Class文件的头4个字节,固定为"0xCAFEBABE",唯一的作用就是确定这个文件是否是一个能够被虚拟机接受的Class文件。
版本号:主次版本号共同决定了Class文件的版本。JVM提供向前兼容性,高版本的JVM可以运行低版本的Class文件,反之不行。《Java虚拟机规范》明确要求了即使文件格式未发生任何变化,虚拟机也必须拒绝执行超过其版本号的Class文件。Class文件版本号对应如下表:

JDK 版本 发行年份 Class 文件主版本号 (major_version) 十六进制表示
JDK 23 (早期访问版) 2024 (预计) 67 0x0043
JDK 22 2024 66 0x0042
JDK 21 (LTS) 2023 65 0x0041
JDK 20 2023 64 0x0040
JDK 19 2022 63 0x003F
JDK 18 2022 62 0x003E
JDK 17 (LTS) 2021 61 0x003D
JDK 16 2021 60 0x003C
JDK 15 2020 59 0x003B
JDK 14 2020 58 0x003A
JDK 13 2019 57 0x0039
JDK 12 2019 56 0x0038
JDK 11 (LTS) 2018 55 0x0037
JDK 10 2018 54 0x0036
JDK 9 2017 53 0x0035
JDK 8 (LTS) 2014 52 0x0034
JDK 7 2011 51 0x0033
JDK 6 2006 50 0x0032
JDK 5 2004 49 0x0031
JDK 1.4 2002 48 0x0030
JDK 1.3 2000 47 0x002F
JDK 1.2 1998 46 0x002E
JDK 1.1 1997 45 0x002D
JDK 1.0.2 1996 45 (及以下) 0x002D

常量池:是Class文件中最复杂、最重要的部分,是所有其他数据结构的引用来源。主要存放字面量符号引用。核心作用是为了解耦,字节码指令、字段名、方法名等不直接存储具体的字符串,而是存储一个指向常量池的索引,使得字节码本身非常紧凑,也为动态链接提供了基础。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值