Hotspot class文件和字节码解析

本文详细介绍了Java Hotspot Class文件的结构,包括整体结构、描述符、常量池信息、字段信息、方法信息和属性信息。同时,探讨了字节码的虚拟机指令定义、内存表示和运行逻辑。最后,介绍了javap命令的使用,包括命令选项和输出说明。通过本文,读者能深入理解Java类文件的内部工作机制。
摘要由CSDN通过智能技术生成

目录

一、class文件

1、整体结构

2、描述符

3、cp_info

4、filed_info

5、method_info

6、attribute_info

二、字节码

1、虚拟机指令定义

2、内存表示

3、运行逻辑

三、javap命令

1、命令选项

2、命令输出说明


前面两篇 《Hotspot Oop模型——Java对象内存表示机制》《Hotspot Klass模型——Java类内存表示机制》讲解了Java类和对象在内存中的表示机制,Java对象是根据Java类创建的,表示一个Java类实例;Java类是根据Class文件创建的,Class文件被类加载器加载、链接、初始化后就变成Hotspot中的Klass。注意这里的Class文件是指符合Class文件格式规范的字节流,并不特指磁盘文件形式的以.class结尾的class文件,如类加载器也可读取网络字节流形式的Class文件。Class文件格式是JVM自己定义的用于表示Java类的二进制字节流规范,与操作系统本身无关,该文件格式正是Java代码一次编译,跨平台运行的关键,其他的与底层操作系统强耦合的编译执行的语言如C/C++需要在每个操作系统上都编译一遍才能正常执行,因为不同操作系统基本都有特定的汇编器和链接器,支持的二进制文件格式也可能不同。那么类的字段,方法,继承的父类,实现的接口等这些信息在Class文件中是如何组织和表示的了?方法对应的字节码是是如何运行的?

一、class文件

1、整体结构

     每个class文件都有一个ClassFile结构,称为Class文件格式,如下图:

其中u<n> 表示n个无符号字节,如u4 magic 表示magic的取值用4个无符号字节表示;cp_info描述常量池的结构,field_info描述字段的数据结构,method_info描述方法的数据结构,attribute_info描述属性的数据结构。ClassFile结构各项的含义如下:

magic: 魔数,用于标识当前Class文件的文件格式,JVM可据此判断该文件是否可以被解析,目前固定为0xCAFEBABE

minor_version, major_version:minor_version是副版本号,major_version是主版本号,这两个版本是生成Class文件时根据编译的JDK版本来确定的,用标识编译时的JDK版本,常见的一个异常Unsupported major.minor version 52.0就是因为运行时的JDK版本低于编译时的JDK版本,52是Java8的主版本号。

constant_pool_count:常量池计数器,等于常量池中的成员数加1。

constant_pool:常量池,是一种表结构,包含class文件结构和子结构中引用的所有字符串常量,类或者接口名,字段名和其他常量,其有效索引范围是1- (constant_pool_count-1)。其中类和接口名采用全限定形式,即在整个JVM中的绝对名称,如java.lang.Object,方法名,字段名、局部变量名和形参名都采用非限定名,即在源代码文件中使用相对名称,如属性名name。

access_flags:用于表示某个类或者接口的访问权限和属性

this_class:类索引,该值必须是对常量池中某个常量的一个有效索引值,该索引处的成员必须是一个CONSTANT_Class_info类型的结构体,表示这个class文件所定义的类和接口

super_class:父类索引,同this_class,该值必须是对常量池中CONSTANT_Class_info类型常量的一个有效索引值,如果该值为0,则只能表示java.lang.Object类,因为该类是唯一一个没有父类的类。

interfaces_count:接口计数器,表示当前类或者接口的直接超接口的数量

interfaces:接口表,是一个表结构,每个成员同this_class,必须是对常量池中CONSTANT_Class_info类型常量的一个有效索引值,其有效索引范围为0~interfaces_count,接口表中成员的顺序与源代码中给定的接口顺序是一致的,interfaces[0]表示源代码中最左边的接口。

fields_count:字段计数器,当前class文件所有字段的数量

fields:字段表,是一个表结构,表中每个成员必须是filed_info数据结构,用于表示当前类或者接口的某个字段的完整描述,不包含从父类或者父接口继承的字段

methods_count:方法计数器,表示当前类方法表的成员个数

methods:方法表,是一个表结构,表中每个成员必须是method_info数据结构,用于表示当前类或者接口的某个方法的完整描述,包含当前类或者接口定义的所有方法,如实例方法、类方法、实例初始化方法等,不包含从父类或者父接口继承的方法

attributes_count:属性计数器,表示当前class文件attributes属性表的成员个数

attributes:属性表,是一个表结构,表中每个成员必须是attribute_info数据结构,这里的属性是对class文件本身,方法或者字段的补充描述,如SourceFile属性用于表示class文件的源代码文件名。

2、描述符

    描述符有两种,字段描述符和方法描述符,本质就是一个基于特定规则的字符串,其中字段描述符用来表示类,实例和局部变量的类型,具体如下:

如I表示一个int变量,Ljava.lang.Object;表示一个Object实例,[[I表示一个二维int数组实例。方法描述符包含一个或者多个参数描述符合一个返回值描述符,参数描述符和返回值描述符都是上面的字段描述符,再加一个特殊的V,表示该方法不返回任何值。如方法Object m(int i, double d, Thread t) {...}对应的方法描述符就是(IDLjava/lang/Thread;)Ljava/lang/Object;

3、cp_info

     Java虚拟机指令不依赖类,接口,类实例或数组的运行时内存布局,而是依赖依赖常量池表中的符号信息,常量池表中所有项都有如下通用格式:

其中tag作为类型标记,用于确定后面的info的格式,tag是一个字节,info是两个或者多个字节,取决于tag的值,如下图:

以CONSTANT_Utf8_info,CONSTANT_Class_info 和CONSTANT_Fieldref_info 的结构为例说明,如下图:

         

CONSTANT_Utf8_info用于表示一个Utf8编码的字符串,tag取值1,length是后面的byte数组的长度,byte数组就是字符串对应的byte数组数据了;

CONSTANT_Class_info用于表示一个Java类或者接口名,的tag取值就是上表中的7,name_index表示对常量池的有效索引,该索引处的成员必须是一个CONSTANT_Utf8_info结构;

CONSTANT_Fieldref_info用于描述一个字段,其中class_index是常量池中的有效索引,该索引处的成员必须是一个CONSTANT_Class_info结构,表示该字段所属的类,name_and_type_index是常量池中的有效索引,该索引处的成员必须是一个CONSTANT_NameAndType_info结构,该结构用于表示一个字段或者方法描述符。

比较特殊的是最后三个,CONSTANT_MethodHandle_info用于表示方法句柄,CONSTANT_MethodType_info用于记录方法的类型信息,即方法描述符,CONSTANT_InvokeDynamic_info用于表示invokedynamic指令使用的动态调用名,参数和返回值等系列静态参数的常量。

4、filed_info

     字段表的成员用field_info结构表示,该结构如下图:

 其中access_flags表示字段的访问权限和属性,是个由标识构成的掩码,所谓标识就是某个特定的二进制位,取值为1表示开启,0表示关闭,各标识开启后的含义如下:

以public static final为例说明,public对应的标识位0000 0000 0000 0001,static对应的标识位是0000 0000 0000 0100,final对应的标识位是0000 0000 0001 0000,合起来就是0000 0000 0001 0101。

name_index表示常量池中一个类型为CONSTANT_Utf8_info的有效索引,表示该字段的字段名

descriptor_index 表示常量池中一个类型为CONSTANT_Utf8_info的有效索引,表示该字段的字段描述符

attributes_count 表示当前字段的附加属性表的属性数量

attributes 属性表,表示该字段的所有附加属性,每个成员都是attribut

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值