JVM学习笔记(7) 第三部分 虚拟机执行子系统 第6章 类文件结构

文章目录

  • [第6章 类文件结构](#第6章 类文件结构)
    • [6.0 个人感悟](#6.0 个人感悟)
    • [6.1 概述](#6.1 概述)
    • [6.2 无关性的基石](#6.2 无关性的基石)
    • [6.3 Class类文件的结构](#6.3 Class类文件的结构)
      • [6.3.1 魔数与版本号](#6.3.1 魔数与版本号)
      • [6.3.2 常量池](#6.3.2 常量池)
      • [6.3.3 访问标志](#6.3.3 访问标志)
      • [6.3.4 类索引、父类索引与接口索引集合](#6.3.4 类索引、父类索引与接口索引集合)
      • [6.3.5 字段表集合](#6.3.5 字段表集合)
      • [6.3.6 方法表集合](#6.3.6 方法表集合)
      • [6.3.7 属性表集合](#6.3.7 属性表集合)

代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言进步的一大步。 --- 《深入理解Java虚拟机》第3版 周志明

第6章 类文件结构

6.0 个人感悟

  1. Class文件的巧妙设计:

    软件工程中有句经典的话:任何问题都可以通过增加一个中间层来解决。字节码文件就是硬件和高级语言之间的那个中间层。

    • 开发人员:只用关注语言使用,各种语法、语法糖,不用关注到底怎么执行
    • 编译部署:平台无关,字节码可以通过JVM到处运行
    • JVM:语言无关,无论哪种语言,符合class格式就认
  2. 向后兼容性的好处:

    时至今日,Class文件格式虽然多次更新,但基本只是在原有结构基础上新增内容、扩充功能,并未对已定义的内容做修改。这种设计保证了Java技术一直保持良好的向后兼容性。

  3. 实践建议:

    如果本章内容感觉抽象,建议动手尝试:

    • 使用 javap -verbose YourClass.class 反编译,对照本章结构理解
    • 用十六进制编辑器直接打开 .class 文件,逐字节解读
    • 尝试编写一个简单的Class文件解析程序,加深对格式的理解

6.1 概述

本章围绕一个核心问题展开:

  1. A: Java源代码(.java文件)经过编译后,究竟变成了什么?
    Q: 答案就是Class文件(也叫字节码文件)。虚拟机并不关心这个Class文件是从哪种语言编译来的,它只认这个统一的二进制格式。

6.2 无关性的基石

平台无关性 :

"一次编写,到处运行"(Write Once, Run Anywhere)是Java诞生之初的口号。这个理想最终实现在操作系统应用层上:各种不同平台的Java虚拟机都可以载入和执行同一种平台无关的字节码,从而实现了程序的跨平台运行。这里的字节码就是构成平台无关性的基石。

语言无关性:

JVM只认Class文件,不管它是Java编译来的,还是Kotlin、Scala编译来的。

6.3 Class类文件的结构

整体特点

Class文件是以8字节为基础单位的二进制流,各个数据项目严格按顺序紧凑排列,中间没有任何分隔符。当遇到需要占用8个字节以上空间的数据项时,按照高位在前(大端模式)的方式分割成若干个8字节进行存储。Class文件格式采用类似于C语言结构体的伪结构来存储数据。

两种数据类型:无符号数和表

  • 无符号数:基本数据类型,用u1、u2、u4、u8分别代表1、2、4、8个字节的无符号数,可描述数字、索引引用、数量值或UTF-8字符串
  • :由多个无符号数或其他表构成的复合数据类型,所有表命名都以"_info"结尾(如cp_info、field_info、method_info等)。整个Class文件本质上也可看作一张表。
    当需要描述同一类型但数量不定的多个数据时,Class文件格式会使用"前置容量计数器 + 若干个连续数据项"的形式,称为"集合"

ClassFile结构体总览

根据《Java虚拟机规范》,Class文件的格式严格限定如下表所示

类型 名称 数量 说明
u4 magic 1 魔数
u2 minor_version 1 次版本号
u2 major_version 1 主版本号
u2 constant_pool_count 1 常量池计数器
cp_info constant_pool[constant_pool_count-1] N 常量池
u2 access_flags 1 访问标志
u2 this_class 1 类索引
u2 super_class 1 父类索引
u2 interfaces_count 1 接口计数器
u2 interfaces[interfaces_count] N 接口索引集合
u2 fields_count 1 字段计数器
field_info fields[fields_count] N 字段表集合
u2 methods_count 1 方法计数器
method_info methods[methods_count] N 方法表集合
u2 attributes_count 1 属性计数器
attribute_info attributes[attributes_count] N 属性表集合

6.3.1 魔数与版本号

魔数

头4个字节,固定值 0xCAFEBABE(咖啡宝贝),用于确定文件是否为合法的Class文件。使用魔数而非扩展名是出于安全考虑

版本号

紧接着的4个字节,第5、6为次版本号,第7、8为主版本号

  • 高版本JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件
  • JDK 8 → 主版本号 52(0x0034),JDK 11 → 55(0x0037)
  • JDK 12之后,次版本号为65535时表示"技术预览版"功能

6.3.2 常量池

常量池是Class文件中与其他项目关联最多的数据,也是第一个出现的表类型数据项目,可理解为"资源仓库"。

  • 常量池计数器:u2类型,从1开始计数,第0项留空(表示"不引用任何常量池项目")。
  • 两大类常量
    • 字面量:如文本字符串、final常量值等。
    • 符号引用:包括包、类和接口的全限定名、字段名称和描述符、方法名称和描述符、方法句柄、动态调用点等。
  • 常量池中每一项都以一个u1类型的tag开头,JDK 1.7之后共有14种不同的表结构。

6.3.3 访问标志

常量池之后的两个字节(access_flags),用于识别类或接口层次的访问信息:是类还是接口?是否为public?是否为abstract?如果是类,是否声明为final?共有16个标志位,当前定义了8个,未使用的必须为0

6.3.4 类索引、父类索引与接口索引集合

  • 类索引(this_class):确定类的全限定名。
  • 父类索引(super_class):确定父类的全限定名。
  • 接口索引集合(interfaces[]):描述该类实现的接口,按implements语句从左到右排列。

6.3.5 字段表集合

字段表(field_info)描述接口或类中声明的变量(类级变量和实例级变量),不包括方法内的局部变量。

  • 字段表集合不会列出从超类或父类接口继承的字段。
  • 字段表结构包含:访问标志、名称索引、描述符索引、属性表集合。名称索引和描述符索引指向常量池中的字符串常量。

6.3.6 方法表集合

方法表(method_info)结构与字段表类似,但访问标志中没有volatile和transient(对方法无意义)

  • 方法表结构包含:访问标志、名称索引、描述符索引、属性表集合。
  • 字节码指令存储位置:方法表的属性表集合中的Code属性------这里存放着真正的字节码指令序列。这也印证了:字节码指令是字节码文件的核心内容,存在于每个方法的Code属性中。

6.3.7 属性表集合

属性表(attribute_info)是Class文件中最灵活的部分,在Class文件、字段表、方法表中都可携带,用于描述某些场景专有的信息。与Class文件其他部分严格顺序不同,属性表集合的顺序要求较宽松

常见属性:

  • Code属性:存储方法体的字节码指令(最关键)。
  • Exceptions属性:方法抛出的异常。
  • LineNumberTable属性:源码行号与字节码指令的对应关系(用于调试)。
  • LocalVariableTable属性:方法局部变量的描述。
  • SourceFile属性:源文件名。
  • ConstantValue属性:final常量值的初始化。
  • InnerClasses属性:内部类信息。
  • Deprecated及Synthetic属性
相关推荐
咖啡忍者1 天前
【SAP CO】4.COPC产品成本控制-3.WIP后台配置
笔记
aWty_1 天前
实分析入门(1)--皮亚诺和自然数
学习
weixin_513449961 天前
walk_these_ways项目学习记录第八篇(通过行为多样性 (MoB) 实现地形泛化)--策略网络
开发语言·人工智能·python·学习
LX567771 天前
传统编辑如何考取AI内容编辑师认证?学习路径详解
人工智能·学习
__土块__1 天前
大厂后端一面模拟:从线程安全到分布式缓存的连环追问
jvm·redis·mysql·spring·java面试·concurrenthashmap·大厂后端
songyuc1 天前
BM2『链表内指定区间反转』学习笔记
学习·链表
L1624761 天前
Kubernetes 完整学习手册(1 主多从 + 纯 YAML 部署 + 访问原理)
学习·容器·kubernetes
weixin_513449961 天前
walk_these_ways项目学习记录第七篇(通过行为多样性 (MoB) 实现地形泛化)--核心环境下
人工智能·python·学习
管鲍考试学习系统1 天前
在线考试系统是什么?功能、部署、应用场景全详解(管鲍考试学习系统 V8.0 深度版)
学习·架构·在线考试·考试系统·培训考试·考试练习