Java虚拟机之Class文件

       Class文件是Java程序的二进制格式,全面描述Java类或者接口。每个Class文件只能描述一个Java类或者接口的全部信息。Class文件的特点 :1. 8位字节的二进制流;2.  按照数据项顺序存储,高位在前;3.  数据项 之间没有间隔。 Java虚拟机是通过读取和解析Class文件来执行Java程序,但是其他一些语言可以编译成Class文件在Java虚拟机上运行。因此,Java虚拟机并不关心Class来源于何种语言,只要符合Class文件的结构规范就可以执行。

       Class文件中只有两种数据类型:无符号数和表。无符号数属于基本的数据类型,以U1、U2、U4、U8来分别代表1个字节、2个字节、4个字节、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

Interfaces_count

U2

Fields_count

1

Field_info

Fields

Fields_count

U2

Methods_count

1

Method_info

Methods

Methods_count

U2

Attributes_count

1

Attribute_info

Attributes

Attributes_count


  下面对各数据项进行简要介绍:
1. 魔数(Magic Number)
    每个Class文件的头4个字节称为魔数(Magic Number),它的唯一作用是判断这个文件是否为能被虚拟机接受的Class文件,其值为0xCAFEBABE。
2. 版本号(Minor_version & Major_version)
     魔数后面的4个字节是Class文件的版本号:第5和第6是次版本号(Minior Version),第7个和第8个字节是主版本号(Major Version)。Class不同的版本,有不同的特性。如果Class文件版本号超出了Java虚拟机能够处理的范围,Java虚拟机将不会处理该 Class文件。
3. 常量池(Constant Pool)
    常量池存储了类和接口相关的常量,主要分 为两大类:字面量和符号引用。字面量比较接近于Java语言层面的常量概念,如文本字符串、被声明为final的常量值等。而符号引用则属于编译原理方面的概念,包括了下面三类常量:类和接口的全限定名;字段的名称和描述符;方法的名称和描述符。
    Class将常量 池组织为入口列表的形式。在常量池入口之前,是入口列表的计数值constant_pool_count,代表常量池的容量。constant_pool_count从1开始计数,第0项腾出来满足后面某些指向常量池的索引值的数据在特定情况下需要表达"不引用任何一个常量池项目"的意思。因此,constant_pool中入口列表的项数,等于constant_poo_count的值减1。Class文件结构中只有常量池的容量计数是从1开始的,对于其他集合类型,包括接口索引集合、字段表集合、方法表集合等的容量计数都是从0开始的。
    常量池中的许多入口都指向其他的常量池入口,而且class文件中紧随常量池的许多条目也会指向常量池的中的入口。 常量池中的每一项常量都是一个表,每个表都是从一个U1类型的tag开始,该tag代表当前对象的常量类型。11种常量类型所代表的具体含义如下表所示:


4. 访问标志(access_flags)
    access_flags展示了类或接口的几段信息。例如:访问标志指明文件中定义的是类还是接口;还定义了在类或接口的声明中,使用了哪种修饰符;类和接口是抽象的,还是公共的;类的类型可以为final,而final类不可能是抽象的;接口不能为final类型的。这些标志位的定义如下表所示:

标志名

设置后的含义

设置者

ACC_PUBLIC

0x0001

Public类型

类和接口

ACC_FINAL

0x0010

类为final类型

只有类

ACC_SUPER

0x0020

使用invokespecial语义

类和接口

ACC_INTERFACE

0x0200

接口类型,不是类类型

所有接口,没有类

ACC_ABSTRACT

0x0400

Abstract类型

所有接口,部分类

5. 类索引(this_class)
    this_class是一个对常量池的索引。在this_class位置的常量池入口必须为CONSTANT_Class_info表。该表由两个部分组成——tag和name_index。tag部分是一个具有CONSTANT_Class值的常量,name_index位置的常量池入口为一个包含了类或接口全限定名的CONSTANT_Utf8_info表。
6. 父类索引(super_class)
    super_class是一个两个字节的常量池索引。在super_class位置的常量池入口是一个指向该类超类全限定名的CONSTANT_Class_info入口。因为Java程序中所有对象的基类都是java.lang.Object类,除了Object类以外,常量池索引super_class对于所有的类均有效。对于Object类,super_class的值为0。对于接口,在常量池入口super_class位置的项为java.lang.Object。
7. 接口(Interfaces)
    interfaces_count表示在文件中由该类直接实现或者由接口所扩展的父接口的数量。在这个计数的后面,是名为interfaces的数组,它包含了对每个由该类或者接口直接实现的父接口的常量池索引。每个父接口都使用一个常量池中的CONSTANT_Class_info入口来描述,该CONSTANT_Class_info入口指向接口的全限定名。这个数组只容纳那些直接出现在类声明的implements子句或者接口声明的extends子句中的父接口。超类按照在implements子句和extends子句中出现的顺序(从左到右)在这个数组中显现。
8. 字段(Fields)
    fields_count表示类变量和实例变量的字段的数量总和。在这个计数后面的是不同长度的field_info表的序列(fields_count指出了序列中有多少个field_info表)。只有在文件中由类或者接口声明了的字段才能在fields列表中列出。在fields列表中,不列出从超类或者父接口继承而来的字段。另一方面,fields列表可能会包含在对应的Java源文件中没有叙述的字段,这是因为Java编译器可以会在编译时向类或者接口添加字段。
field_info表的格式如下所示:
类型
名称
说明
数量
U2
access_flags
字段访问权限
1
U2
name_index
字段名称
1
U2
descriptor_index
字段描述符
1
U2
attributes_count
attributes 项目数
1
attribute_info
attributes
attribute_info 列表
attributes_count
access_flags指定字段的访问修饰符,所使用的标志位如下表所示:

标准名称

设定含义

设定者

ACC_PUBLIC

0x0001

public

类和接口

ACC_PRIVATE

0x0002

private

只有类

ACC_PROTECTED

0x0004

protected

只有类

ACC_STATIC

0x0008

static

类和接口

ACC_FINAL

0x0010

final

类和接口

ACC_VOILATIE

0x0040

volatile

只有类

ACC_TRANSIENT

0x0080

transient

只有类

name_index提供字段名称的 CONSTANT_Utf8_info表的索引
descriptor_index  提供字段描述符的 CONSTANT_Utf8_info表的索引
attributes项由多个attribute_info表组成的 列表,可以有任意数量的属性
   9. 方法(Methods)
    methods_count表示该类或者接口中声明多的所有方法的数量总和,只包括该类或者接口中显式定义的方法,不包括超类或者父接口中继承来的方法。method_info表包含了与方法相关的信息,包括方法名和描述符(返回值类型和参数类型、顺序和数量)。
method_info表的格式如下所示:
类型
名称
说明
数量
U2
access_flags
方法访问权限
1
U2
name_index
方法名称
1
U2
descriptor_index
方法描述符
1
U2
attributes_count
attributes  项目数
1
attribute_info
attributes
attribute_info  列表
attributes_count
access_flags指定方法的访问修饰符,所使用的标志位如下表所示:

标准名称

设定含义

设定者

ACC_PUBLIC

0x0001

public

类和所有的接口方法

ACC_PRIVATE

0x0002

private

只有类

ACC_PROTECTED

0x0004

protected

只有类

ACC_STATIC

0x0008

static

只有类

ACC_FINAL

0x0010

final

只有类

ACC_SYNCHRONIZED

0x0020

synchronized

只有类

ACC_NATIVE

0x0100

native

只有类

ACC_ABSTRACT

0x0400

abstract

类和所有的接口方法

ACC_STRICT

0x0800

strictFP

类和接口的<clinit>方法

method_info表的其他项的含义给跟field_info表的差不多。
10. 属性(Attributes)
    Attributes给出了在该文件类或者接口所定义的属性的基本信息。属性部分由attributes_count开始,attributes_count是指出现在后续attributes列表的attribute_info表的数量总和。每个attribute_info的第一项是指向常量池中CONSTANT_Utf8_info表的索引,该表给出了属性的名称。
    属性出现在class文件的多处,不同地方用到的属性的种类也不同。Java虚拟机定义了9种属性,如下表所示:

名称

使用者

描述

Code

method_info

方法的字节码和其他数据

ConstantValue

field_info

Final变量的值

Deprecated

field_info, method_info

字段或方法被禁用指示符

Exceptions

method_info

方法抛出的可被检测的异常

InnerClasses

ClassFile

内部、外部类的列表

LineNumberTable

Code_attribute

方法的行号与字节码的映射

LocalVariableTable

Code_attribute

方法局部变量的描述

SourceFile

ClassFile

源文件名

Synthetic

field_info, method_info

编译器产生的字段或方法的指示符


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值