什么是 Class 文件?
在 Java 刚刚诞生的时候就提出了一个非常著名的口号:"一次编写, 到处运行.(Write Once,Run Anywhere)". 为了实现平台无关性, 各种不同平台的虚拟机都统一使用一种程序储存格式, 就是字节码(ByteCode). 它就以二进制字节流的方式被存放在 Class 文件中, 其中包含了 Java 虚拟机指令集和符号表以及其他辅助信息.
为什么需要了解 Class 文件结构?
一般对于数据结构的分享难免比较枯燥, 但是了解 Class 文件结构是了解 Java 虚拟机的重要基础之一. 如果想比较深入地了解 Java 虚拟机, 那么 Class 文件结构是不能不接触的. 我会力求在保证逻辑准确的基础上, 尽量通俗易懂地分享, 并结合实际案例.
Class 文件结构简介
Class 文件是一组以 8 位字节为基础单位的二进制流, 各个数据项目严格按照顺序准确地排列在 Class 文件中, 中间没有任何分隔符. 当遇到 8 位字节以上的数据时, 就按照高位在前的方式 (最高位字节在地址最低位, 最低位字节在地址最高位的顺序储存) 分割成多个 8 位字节储存.
Class 文件格式采用一种类似于 C 语言结构体的伪结构来储存数据的, 这种伪结构有两种数据类型: 无符号数和表.
无符号数用 u1,u2,u4,u8 分别代表 1 个字节, 2 个字节, 4 个字节和 8 个字节的无符号数, 可以用来描述数字, 索引引用, 数量值或者 UTF-8 编码构成的字符串值.
表是由多个无符号数或其他表作为数据项构成的复合数据类型, 所有的表都习惯地以 "_info" 结尾. 表的数据结构和树很类似, 无符号数相当于它的叶子节点, 其他的表相当于它的子节点. 整个 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 | 常量池 |
u2 | access_flags | 1 | 访问标志 |
u2 | this_class | 1 | 类索引 |
u2 | super_class | 1 | 父类索引 |
u2 | interfaces_count | 1 | 接口索引计数值 |
u2 | interfaces | interface_count | 接口索引 |
u2 | fields_count | 1 | 字段计数值 |
field_info | fields | fields_count | 字段 |
u2 | methods_count | 1 | 方法计数值 |
method_info | fields | methods_count | 方法 |
u2 | attributes_count | 1 | 属性计数值 |
attribute_info | attributes | attributes_count | 属性 |
可以发现, 无论是无符号数还是表, 当需要描述同一种类型又数量不定的多条数据时, 就会用一个前置的计数器加几个连续的数据项的方式, 这个时候我们就把这种一系列连续的某种类型的数据叫做这个类型的集合.
在 Class 文件中, 无论是顺序还是数量, 甚至是数据存储的字节序, 都必须严格按照上面表格进行设定, 哪个字节代表什么含义, 长度是多少, 先后顺序怎么样, 都不允许改变. 接下来看一下各个数据项的具体含义.
- public class OneMoreStudy {
- private int number;
- private int plusOne() {
- return number + 1;
- }
- }
- E:\>javap -verbose OneMoreStudy
- Compiled from "OneMoreStudy.java"
- minor version: 0
- major version: 51
- Constant pool:
- #1 = Methodref #4.#15 // java/lang/Object."<init>":()V
- #2 = Fieldref #3.#16 // OneMoreStudy.number:I
- #3 = Class #17 // OneMoreStudy
- #4 = Class #18 // java/lang/Object
- #5 = Utf8 number
- #6 = Utf8 I
- #7 = Utf8 <init>
- #8 = Utf8 ()V
- #9 = Utf8 Code
- #10 = Utf8 LineNumberTable
- #11 = Utf8 plusOne
- #12 = Utf8 ()I
- #13 = Utf8 SourceFile
- #14 = Utf8 OneMoreStudy.java
- #15 = NameAndType #7:#8 // "<init>":()V
- #16 = NameAndType #5:#6 // number:I
- #17 = Utf8 OneMoreStudy
- #18 = Utf8 java/lang/Object
来源: https://www.cnblogs.com/heihaozi/p/11887042.html