JVM循序渐进(一) 浅识class文件


JVM循序渐进(一) 浅识class文件

jvm系列文章基本结构(红色区域为本文重点介绍内容)

本文希望可以从.java文件的编译,class文件的加载,最终在虚拟机中的运行整个过程进行描述。 作为学习虚拟机过程中的一个总结和输出,本来想法是用视频的方式,但是暂时还没办法实现....,可能以后会有吧。


简单介绍class文件内容,重点了解常量池是如何布局的

首先java文件编译成为class字节码文件之后,在sublime等文本编辑器中打开是一堆16进制的编码,如图所示:

JVM循序渐进(一) 浅识class文件

字节码文件16进制 - 图1

而字节码文件的各部分表示含义如图所示:

JVM循序渐进(一) 浅识class文件

class字节码文件结构 - 图2

1.魔数

每一个class文件的头4个字节称为魔数,它唯一的作用是确定这个文件是否为一个能被虚拟机接受的Class文件。

2.版本

第五六个字节是次版本(Minor Version)。第7和第8个字节是主版本(Major Version)。

3.常量池 (class字节码文件中的重点,也是相对最复杂的一部分)

constant_pool_count:占2字节。0x0016。转化为十进制为22,即说明常量池中有21个常量(仅仅有常量池的计数是从1開始的,其他集合类型均从0開始),索引值为1~22。第0项常量具有特殊意义。假设某些指向常量池索引值的数据在特定情况下须要表达“不引用不论什么一个常量池项目”的含义,这样的情况能够将索引值置为0来表示。

常量池中主要存放两大类常量:字面量和符号引用。字面量如文本字符串、声明为final的常量值等。符号引用包含三类常量:类和接口的全限定名、字段的名称和描写叙述符、方法的名称和描写叙述符。

constant_pool_count之后则是常量池的具体内容:


我对图1中的16进制字节码文件的前几个字节进行了解析:在前面一些标识符号之后(即从第11个字节开始)以 0a00 0a00 1e为例

0a转化为10进制是10,代表的是常量池表中的flag=10的那一项,常量池表如图所示(选取了一部分截图):

JVM循序渐进(一) 浅识class文件

常量池表 -图3

0a 代表的就是CONSTANT_Methodref_info

CONSTANT_Methodref_info中的两项内容为该项标识所属的类、和该项标识方法的信息(参数返回值类型等),分别为

CONSTANT_NameAndType_info和CONSTANT_Class_info,而这两项其中又包含了其他的常量池引用。

大体结构:

CONSTANT_Methodref_info---

----CONSTANT_Class_info

----CONSTANT_Utf8_info

----CONSTANT_NameAndType_info

----CONSTANT_Utf8_info

----CONSTANT_Utf8_info

分析图如下:

JVM循序渐进(一) 浅识class文件

对字节码文件的简单分析 - 图4

CONSTANT_Methodref_info---

----CONSTANT_Class_info

----CONSTANT_Utf8_info:java/lang/Object

----CONSTANT_NameAndType_info

----CONSTANT_Utf8_info:<<init>>/<init>

----CONSTANT_Utf8_info

可以看到常量池中的成员其实是在互相引用(在idea中下载一个jclasslib插件,可以可视化的看到字节码的结构):

JVM循序渐进(一) 浅识class文件

jclasslib中看到的字节码文件中常量池互相引用 - 图5

4.訪问标志


JVM循序渐进(一) 浅识class文件

访问标识表

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

this_class:类索引,用于确定这个类的全限定名,占2字节

super_class:父类索引。用于确定这个类父类的全限定名(Java语言不同意多重继承,故父类索引仅仅有一个。

除了java.lang.Object类之外全部类都有父类,故除了java.lang.Object类之外,全部类该字段值都不为0),占2字节

interfaces_count:接口索引计数器。占2字节。

假设该类没有实现不论什么接口。则该计数器值为0,而且后面的接口的索引集合将不占用不论什么字节。

interfaces:接口索引集合,一组u2类型数据的集合。用来描写叙述这个类实现了哪些接口。这些被实现的接口将按implements语句(假设该类本身为接口,则为extends语句)后的接口顺序从左至右排列在接口的索引集合中

6.字段表集合

fields_count:字段表计数器。

fields:字段表集合,

7.方法表集合

8.属性表集合


分享到:


相關文章: