【JVM】详解 Class类文件的结构

目录

魔数与版本号

常量池

访问标志

类索引、父类索引和接口索引集合

字段表

方法表

属性表

Code属性

Exceptions属性


Class文件是以八字节为基础单位的二进制流,任何一个Class文件都对应着唯一的一个类或接口的定义信息。

Class文件格式采用"无符号数 "和"表"来记录数据:

  • 无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。
  • 表是由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都习惯性地以"_info"结尾。

Class文件格式如图

魔数与版本号

Class文件的头四个字节为魔数(Magic Number),用来确定Class文件是否能被JVM接受。

紧跟着的4个字节就为版本号,第5和第6个字节是 次版本号(Minor Version),第7和第8个字节是主版本号(MajorVersion) 。版本号目的是让对应的JDK运行对应版本的Class文件,高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件。

常量池

常量池为表类型 的数据,可以理解为Class文件的资源库。

在版本号之后的就是常量池入口,常量池入口中放置了u2类型的数据,代表常量池容量计数值(constant_pool_count)。

常量池中每一项常量都是一个表。常量池主要存放两大类常量:字面常量(Literal) 和符号引用(SymbolicReferences):

字面常量 接近Java中的常量概念,如字符串,final修饰的常量值等。

符号引用则属于编译原理方面的概念,主要包括下面几类常量:

  • 被模块导出或者开放的包(Package)
  • 类和接口的全限定名(Fully Qualified Name)
  • 字段的名称和描述符(Descriptor)
  • 方法的名称和描述符
  • 方法句柄和方法类型(Method Handle、Method Type、InvokeDynamic)
  • 动态调用点和动态常量(Dynamically-Computed Call Site、Dynamically-Computed Constant)

访问标志

常量池之后就是访问表示,用来标记类和接口的访问信息 ,包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract类型;如果是类的话,是否被声明为final等等。

类索引、父类索引和接口索引集合

类索引(this_class)和父类索引(super_class) 都是一个u2类型的数据,而**接口索引集合(interfaces)**是一组u2类型的数据的集合。这三个数据类型决定了Class文件对应的类的继承关系。

字段表

**字段表(field_info)**用于描述接口或者类中声明的变量。结构如下图。

字段可以包括的修饰符有:字段的作用域 (public、private、protected修饰符)​、是实例变量还是类变量 (static修饰符)​、可变性 (final)、并发可见性 (volatile修饰符,是否强制从主内存读写)​、可否被序列化 (transient修饰符)​、字段数据类型 (基本类型、对象、数组)​、字段名称。

上述可以用bool类型 的标志位来表示,通过放在access_flags字段修饰符在其中设置标志位。

跟随access_flags标志的是两项索引值:name_index和descriptor_index。它们都是对常量池项的引用,分别代表着字段的简单名称以及字段和方法的描述符。

字段表集合中不会列出从父类或者父接口中继承而来的字段 ,但有可能出现原本Java代码之中不存在的字段,譬如在内部类中为了保持对外部类的访问性,编译器就会自动添加指向外部类实例的字段。

方法表

方法表的结构如同字段表一样,依次包括访问标志(access_flags)、名称索引(name_index)、描述符索引(descriptor_index)、属性表集合(attributes)。

在Java语言中,要重载(Overload)一个方法,除了要与原方法具有相同的简单名称之外,还要求必须拥有一个与原方法不同的特征签名 。特征签名是指一个方法中各个参数在常量池中的字段符号引用的集合。但如果两个方法简单名称、特征签名相同,返回值不同,也可以被视作重载的不同方法。

属性表

Class文件、字段表、方法表都可以携带自己的属性表集合 ,以描述某些场景专有的信息。结构如下图。

Code属性

Java程序方法体里面的代码经过Javac编译器处理之后,最终变为字节码指令存储在Code属性内。

try-catch代码块中的异常通过异常表来处理。

Exceptions属性

Exceptions属性的作用是列举出方法中可能抛出的受查异常(Checked Excepitons),也就是方法描述时在throws关键字后面列举的异常。与异常表中处理的异常不同。

相关推荐
阿俊-全栈开发1 小时前
LikeShop 版本升级与备份:从旧版平滑迁移的完整步骤
jvm·数据库·oracle·开源·likeshop·likeshop开源商城
huaweichenai1 小时前
spring boot对接阿里短信
java·spring boot
KING-WU5121 小时前
Linux 工具之Make 与 Makefile
java·linux·服务器
马剑威(威哥爱编程)2 小时前
【AI全栈后端12-08】Spring Boot 用 MCP 统一接入内部系统:让 AI 接一次,全公司复用
java·人工智能·spring boot
顽疲2 小时前
从零用 Java 实现小红书 SpringBoot Vue UniApp(23)笔记话题多对多:一条笔记进多个话题池
java·vue.js·spring boot
木井巳2 小时前
【BFS 解决拓扑排序】课程表
java·算法·leetcode·广度优先·宽度优先·推荐算法·图搜索算法
Crazy________2 小时前
05Linux内存管理核心原理与运维实战
java·开发语言
Nebula_g2 小时前
JavaSE拓展:工具类Executors
java·开发语言·后端·spring·基础·javase
长弓三石2 小时前
企业级Harness开源平台BizBuddy适配AgentScope-2.0.4并发布0.7.0版本
java·人工智能·aigc
扶风ff2 小时前
练题簿在线免费刷题:会员线下组卷、Word 试卷与成绩导入,课堂检测更方便
java·开发语言·算法·小程序·word