现在的位置: 首页 > 综合 > 正文

JVM Class 文件结构详解一

2017年06月10日 ⁄ 综合 ⁄ 共 2286字 ⁄ 字号 评论关闭

      Class文件的存储结构使得Java虚拟机实现了语言无关性,不同的语言,如java、groovy等程序语言通过编译可以转化为存储字节码的Class文件,从而使得Class文件在虚拟机中运行。

1、Class文件的结构

      Class文件是一组以8位字节为单位的二进制流,各数据项严格按照顺序紧凑的排列在Class文件之中,中间无任何分隔符号。根据JVM Specification规定,Class文件格式采用一种类似于C语言结构体的伪结构来存储。这种伪结构中只有两种数据类型:无符号数和表。

      无符号数:基本数据类型,以u1、u2、u4和u8分别代表1个字节、2个字节、4个字节和8个字节的无符号数,用于描述数字、索引引用、数量值等。

      表:由多个无符号数或其他表作为数据项构成的复合数据类型,以_info结尾,用于描述有层次关系的复合机构的数据。

      下图是Class文件格式:

                

      为了方便解释,编写如下简单代码:

package cn.com.yy;

/**
 * Class文件结构
 * @author yy
 * @time 2014-9-22 下午9:57:50
 */
public class ClassFileTest {

	private int count;
	
	public int returnValue(){
		return count;
	}
}

(1)magic

      magic,称之为魔数,是Class文件的前4个字节,作用为用于确定这个文件是否为一个能被虚拟机接受的Class文件。值为0xCAFEBABE。上述代码编译后,打开Class文件,显示如下图:

                

      可以看出,Class文件的前4个字节为magic的值。

(2)Class文件的版本

      接下来的第5个字节和第6个字节是Class文件的次版本号,第和第8字节为主版本号,如下图:

                

      从图中可以看出,次版本号为0x0000,主版本号为0x0032,主版本号为十进制的50,说明该Class文件可以被JDK1.6或以上版本的虚拟机执行。下图为Class文件的版本号:

                

      从图中可以看出,从JDK1.3后,就没有此版本号了,只有主版本号。

      需要注意的是:某个版本的JVM能接受Class文件的最大主版本号不能超过对应JDK带对应target参数编译出来的Class文件的版本号。举例:JVM1.4能接受的Class文件的主版本号不能超过1.4JDK -target 1.4时编译出的Class文件的主版本号:48。

(3)常量池个数和常量池

      接下来为2个字节的常量池个数:

                

      该程序的constant_pool_count为0x0016,即十进制的22,代表着常量池中有21项常量,索引为1~21(索引为0的不算)。具体的常量值可以通过命令javap -verbose className获悉,如下:

                

      在字节码文件中显示的区域为下:

                

      途中红色线框包含的区域为常量区。

      对于常量池,池中的每一个项常量都是一个表,共有11种结构不通的表结构数据。如下图所示:

                

      上图中的每个表有一共同特点:表开始的第一位是一个u1类型的标志位(tag,取值为1,。。。12,没有2)。且每个表的结构都不同,下图中列出了每种数据表的结构,如下图所示:

                         

类型

项目

类型

描述

CONSTANT_Utf8_info

tag

u1

 

值为1

length

u2

UTF-8编码的字符串占用的字节数

bytes

u1

长度为length的UTF-8编码的字符串

CONSTANT_Integer_info

tag

u1

值为3

bytes

u4

按照高位在前存储的int值

CONSTANT_Float_info

tag

u1

值为4

bytes

u4

按照高位在前存储的float值

CONSTANT_Long_info

tag

u1

值为5

bytes

u8

按照高位在前存储的long值

CONSTANT_Double_info

tag

u1

值为6

bytes

u8

按照高位在前存储的double值

CONSTANT_Class_info

tag

u1

值为7

index

u2

指向全限定名常量项的索引

CONSTANT_String_info

tag

u1

值为8

index

u2

指向字符串字面量的索引

CONSTANT_Fieldref_info

tag

u1

值为9

index

u2

指向声明字段的类或接口描述符CONSTANT_Class_info的索引项

index

u2

指向字段描述符CONSTANT_NameAndType_info的索引项

CONSTANT_Methodref_info

tag

u1

值为10

index

u2

指向声明方法的类描述符CONSTANT_Class_info的索引项

index

u2

指向名称及类型描述符CONSTANT_NameAndType_info的索引项

CONSTANT_InterfaceMethodref_info

tag

u1

值为11

index

u2

指向声明方法的接口描述符CONSTANT_Class_info的索引项

index

u2

指向名称及类型描述符CONSTANT_NameAndType_info的索引项

CONSTANT_NameAndType_info

tag

u1

值为12

index

 

u2

指向该字段或方法名称常量项的索引

index

u2

指向该方法或方法描述符常量项的索引

      针对JVM Class文件结构中的其他内容请参考文章JVM Class 文件结构详解二

抱歉!评论已关闭.