- 6.1 概述
- 越来越多的程序语言选择了与操作系统和机器指令集无关的、平台中立的格式作为程序编译后的存储格式
- 6.2 无关性的基石
- 平台无关性:Java虚拟机可以运行在不同的硬件平台和操作系统上,这些虚拟机可以载入和执行同一种字节码文件,实现“一次编写,到处运行”
- 语言无关性:任意一门功能性语言都可以表示为一个能被Java虚拟机所接受的有效的Class文件。作为一个通用的、与机器无关的执行平台,任何其他语言的实现者都可以将Java虚拟机作为他们语言的运行基础,以Class文件作为他们产品的交付媒介。字节码指令所能提供的语言描述能力比Java语言本身更加强大
- 在日常交流中,人们常会说“Java 跑的是字节码”或“把 .class 字节码文件给我”,这种情况下两者基本可以等同。但严格来说:字节码是 JVM 执行的指令,.class 文件是字节码的载体,但 .class 文件不只包含字节码
如果把一个 <code>.class</code> 文件想象成一个“产品包裹”。
那么字节码就是包裹里那个核心的“商品”(即方法的执行逻辑)。
但是这个包裹上还必须有“快递单”和“说明书”(即元数据),包括:
魔数 (Magic Number): 确认这确实是一个 <code>.class</code> 文件 (<code>0xCAFEBABE</code>)。
版本号: 编译这个文件的 JDK 版本。
常量池 (Constant Pool): 存放所有的字面量、类名、方法名、字段名等。
类信息: 这个类叫什么名字?(<code>this_class</code>)
父类和接口: 它继承了谁?(<code>super_class</code>) 实现了哪些接口?(<code>interfaces</code>)
字段表 (Fields): 它有哪些成员变量?
方法表 (Methods): 它有哪些方法?(字节码主要就存放在这里,作为方法的 Code 属性)。
- 6.3 Class类文件的结构
- 任何一个Class文件都对应着唯一的一个类或接口的定义信息,但是反过来说,类或接口并不一定都得定义在文件里因为类或接口也可以动态生成,直接送入类加载器中
- Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。当遇到需要占用8个字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8个字节进行存储。
- Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:“无符号数”和“表”
- 无符号数:基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。
- 表:多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都习惯性地以“_info”结尾。表用于描述有层次关系的复合结构的数据,整个Class文件本质上也可以视是一张表,这张表由表所示的数据项按严格顺序排列构成。
- 6.3.1 魔数与Class文件的版本
- 魔数:每个Class文件的头4个字节,它的唯一作用是确定这个文件是否为 一个能被虚拟机接受的Class文件
- 次版本号:第5和第6个字节
- 主版本号:第7和第8个字节
- 6.3.2 常量池
- 紧接着主、次版本号之后的是常量池入口
- 由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值,这个容量计数是从1而不是0开始的,因为0表示不引用任何一个常量池项目
- 主要存放两大类常量:
- 字面量:字面量比较接近于Java语言层面的常量概念,如文本字符串、被声明为final的常量值等
- 符号引用:一个描述性的标识符,它以一组文本符号的形式,定义了在程序中被引用的一个目标,是一种逻辑上的引用。这个目标可以是类、接口、字段或方法。编译后即固定,是静态的。不依赖任何具体的JVM内存实现,在解析阶段被转换为直接引用。主要包含:
- 被模块导出或者开放的包
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
- 方法句柄和方法类型
- 动态调用点和动态常量
- 常量池中每一项常量都是一个表,表结构起始的第一位是个u1类型的标志位
- 6.3.3 访问标志
- 在常量池结束之后,紧接着的2个字节代表访问标志。这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract类型;如果是类的话,是否被声明为final;等等。
- 在常量池结束之后,紧接着的2个字节代表访问标志。这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract类型;如果是类的话,是否被声明为final;等等。
《深入理解Java虚拟机》第六章学习笔记:类文件结构
张小明
前端开发工程师
DIVA安卓逆向
打开APP,进入第一关检测不通过翻译在日志中?失败了,直接白屏,app直接崩了?修改代码报错Log.d存在多个重载版本修改脚本找到了日志泄露根据字符在jadx中搜索一下泄露的源码
不拼参数拼“榨干”:海外开发者盯上4B小模型,一台家用电脑就能吐出3D世界
不拼参数拼“榨干”:海外开发者盯上4B小模型,一台家用电脑就能吐出3D世界 最近AI圈的风向有点意思。 前两年大家见面就问“你多少B”,好像参数不到千亿都不好意思打招呼。可这两个月,海外开发者社区里最热的话题反过来了——怎么把…
EPLAN 部件库用成考古现场?3000条部件数据批量清洗与回灌的完整记录
上季度新项目要出采购 BOM,EPLAN 的部件汇总表导出来一看,采购直接打回来了:同一个 9A 交流接触器在库里躺着三种写法——3RT2016-1BB41、3RT2 016-1BB41(订货号中间多了个空格)、还有一条类型描述写"西门子接触器…
Linux入门第二部分(ARM裸机篇) 第三章 汇编LED驱动实验
参考教程:正点原子【第二期】手把手教你学Linux之ARM(MX6U)裸机篇_哔哩哔哩_bilibili 一、I.MX6ULL IO命名与配置寄存器 1、STM32引脚的命名与相关寄存器 (1)在STM32中,引脚的命名简单直观,比…
机器人自动化装配线 SPC 控制图工程实战案例与计算报告
1. 工程背景与工艺质量特性(CTQ)定义在某新能源动力电池包(PACK)智能化装配线上,工位 OP30 部署了一台六轴机器人搭载高精度伺服智能拧紧枪,执行电池包上盖 M6 结构螺栓的高速自动化定扭紧固工艺࿰…
Abaqus 二次开发教程(4):Python 2 → 3.10 迁移实战——换解释器不是换版本,是断兼容
Abaqus 二次开发教程(4):Python 2 → 3.10 迁移实战——换解释器不是换版本,是断兼容版本声明块 工具/软件:Abaqus 2026(2026 FD01),内嵌 Python 3.10.5(2024 GA 起&…