java类文件结构

任何Java程序都要经过jvm虚拟机的处理生成class文件,然后然后虚拟机去解析class文件,下面我们来介绍一下class文件的结构。

  Class文件格式采用的是类似于C语言的结构体的伪结构来存储数据,这种伪结构只有两种数据类型:无符号数和表;

  无符号数属于基本的数据类型,以u1,u2,u3,u4,u8来代表1个字节、2个字节、4个字节、8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值;

  表是由多个无符号数或者是其他表作为数据项构成的复合数据类型,所有表都习惯以“_info”结尾。整个Class文件本质上就是一张表。

  Class文件不像XML文件那样,由于没有任何的分隔符号,所以对于顺序和数量,甚至于数据存储的字节序这样的细节,都是被严格限定的,哪个字节代表什么顺序,长度是多少,都是不允许改变的。

  每个Class文件的头4个字节都称为魔数,它的唯一作用就是判断该文件是否是一个能被虚拟机接收的Class文件。紧接着魔数的4个字节存储的是Class文件的版本号:第5和第6个字节存储的是次版本号(Minor Version),第7和第8个字节存储的是主版本号(Major Version),Java版本号是从45开始的。

  下面分析一个简单的Java程序对应的Class文件

  源文件

class Test0 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
                System.out.println("123");

    }

}

对应的Class文件

java类文件结构_第1张图片

这里的第八个字节值对应的十进制就是50,该版本号说明这个文件是可以被JDK1.6或者以上版本虚拟机执行的Class文件。


紧接着主次版本号之后的是常量池入口,常量池可以理解为Class文件中的资源仓库,由于常量池中的常量数量不固定的,所以统一在和常量池的入口处需要存放一个u2(两个字节)类型的数据,代表常量池容量计数值,与Java中语言习惯不一样的是,这个计数是从1开始的而不是从0开始,Class文件中只有常量池的容量计数是从1开始的,对于其他的集合类型,包括接口索引集合,字段表集合,方法表集合等的容量计数都是从0开始的,图中0x001D表示的十进制数29表示常量池中有28项常量。字节码的转化按照十六进制ASCII标准

java类文件结构_第2张图片

常量池中主要存放两大类常量:字面量和符号引用,字面量比较接近Java语言层次的常量概念,如文本字符串,申明为final的常量值等,而符号引用则属于编译原理方面的概念,包括下面三类常量:类和接口的全限定名,字段的名称和描述符,方法的名称和描述符。  当虚拟机运行时,就会从和常量池中获取对应的符号引用,再在类创建或者运行时解析,翻译到具体的内存地址之中。(常量池中的每一项常量都是一个表,JDK1.7中又额外增加了3种表结构数据,拥有14种表结构数据)。

  java类文件结构_第3张图片

如表1-1是常量池的项目类型

可以看出,示例Class中第一项常量,它的标志位是0x0A,查表1-1可知这个常量属于CONSTANT_Methodref_info类型,此类型的常量代表类中方法的符号引用。

     之所以说常量池是最烦琐的数据,是因为这14种常量类型各自拥有自己的结构。

本例中一共有28个常量,其余的27个常量我们可以交由Oracle提供的专门用于分析Class文件字节码的工具:Javap;效果如图1-1

java类文件结构_第4张图片

图1-1  使用Javap命令输出常量表


未完待续。。。


你可能感兴趣的:(java,jvm,Class字节码)