Class字节码文件

概述

Java源代码的编译结果是字节码,那么肯定需要有一种编译器能够将Java源码编译为字节码,承担这个重要责任的就是配置在path环境变量中的javac编译器。javac是一种能够将Java源码编译为字节码的前端编译器。

源代码经过编译器编译之后便会生成一个字节码文件,字节码是一种二进制的类文件,它的内容是JVN的指令,而不像C、C+t经由编译器直接生成机器码。

Java的跨平台性:

Java虚拟机不和包括 Java 在内的任何语言绑定,它只与“Class 文件”这种特定的二进制文件格式所关联。无论使用何种语言进行软件开发,只要能将源文件编译为正确的Class文件,那么这种语言就可以在Java虚拟机上执行。

class字节码文件可以通过JDK自带的javap命令来反编译查看

字节码文件结构

Class文件的总体结构如下:

  • 魔数

    • 类型:u4(4个字节的无符号整数)

    • 名称:magic

    • 说明:用于识别Class文件格式

  • Class文件版本

    • 类型:u2+u2(4个字节的无符号整数)

    • 名称:minor_version+major_version

    • 说明:包含一个副版本号(minor_version),在第5,6字节;一个主版本号(major_version),在7,8字节

  • 常量池

    常量池是class文件中内容最为丰富的区域之一。常量池对于Class文件中的字段和方法解析也有着至关重要的作用。

    常量池计数器:

    • 类型:u2

    • 名称:constant_pool_count

    • 说明:由于常量池的数量不固定,时长时短,所以需要放置两个字节来表示常量池容量计数值。(0项被空出来了)

    常量池表:

    • 类型:cp_info

      1
      2
      3
      4
      5
      6
      cp_info{
      // 标识是什么类型的表项
      u1 tag;
      // 具体内容
      u1 info[];
      }
    • 名称:constant_pool

    • 说明:常量池的映射表,用于存放编译时期生成的各种字面量符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放

    虚拟机在加载cClass文件时才会进行动态链接,也就是说,Class文件中不会保存各个方法和字段的最终内存布局信息,因此,这些字段和方法的符号引用不经过转换是无法直接被虚拟机使用的。当虚拟机运行时,需要从常量池中获得对应的符号引用,再在类加载过程中的解析阶段将其替换为直接引用,并翻译到具体的内存地址中。

  • 访问标志

    • 类型:u2

    • 名称:access_flag

    • 说明:在常量池后,紧跟着访问标记。该标记使用两个字节表示,用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类型,是否定义为 abstract类型;如果是类的话,是否被声明为 final等。

      image-20230405111137144

  • 类索引,父类索引,接口索引集合

    类索引:

    • 类型:u2

    • 名称:this_ckass

    • 说明:类索引用于确定这个类的全限定名

    父类索引:

    • 类型:u2

    • 名称:super_class

    • 说明:父类索引用于确定这个类的父类的全限定名。由于Java语言不允许多重继承,所以父类索引只有一个,除了java.lang.0bject之外,所有的Java类都有父类,因此除了java.lang.Object 外,所有Java类的父类索引都不为0。

    接口索引:

    • 类型:u2+u2*interfaces_count

    • 名称:interfaces_count+interfaces[interfaces_count]

    • 说明:接口索引集合就用来描述这个类实现了哪些接口,这些被实现的接口将按 implements 语句(如果这个类本身是一个接口,则应当是extends 语句)接口顺序从左到右排列在接口索引集合中。

  • 字段表集合

    字段表计数器:

    • 类型:u2
    • 名称:fields_count
    • 说明:fields_count的值表示当前class文件fields表的成员个数。

    字段表集合:

    • 结构:

      image-20230406142150976

    • 说明:用于描述接口或类中声明的变量。字段(field)包括类级变量以及实例级变量,但是不包括方法内部、代码块内部声明的局部变量。( local variables)

  • 方法表集合

    方法表计数器:

    • 类型:u2
    • 名称:methods_count
    • 说明:methods_count的值表示当前class文件methods表的成员个数。

    方法表集合:

    • 结构:

      image-20230406142446016

    • 说明:指向常量池索引集合,它完整描述了每个方法的签名。

  • 属性表集合

    属性表计数器:

    • 类型:u2
    • 名称:attributes_count
    • 说明:attributes_count的值表示当前class文件属性表的成员个数。

    属性表集合:

    • 结构:

      image-20230406143118124

    • 说明:方法表集合之后的属性表集合,指的是class文件所携带的辅助信息,比如该class 文件的源文件的名称。以及任何带有RetentionPolicy.CLASS或者RetentionPolicy.RUNTIME的注解。