JVM Class文件格式

无关性基石

JVM虚拟机不和包括Java的具体语言绑定,而是和Class文件这种特定格式的二进制文件相关联,所以只要能编译出合法Class文件的都能使用JVM运行。
所以Class文件支持超过Java语义的东西,比如允许根据返回值不同进行方法重载等。

Class文件格式

  • 任意一个Class文件一定对应着一个唯一的类或接口信息,但是反过来,类或接口并不一定都要定义在Class文件里。比如类或接口也可以通过类加载器直接生成。
  • Class文件存在两个数据类型:无符号数和表。
    • 无符号数:可以表示字符串、数值等。
    • 表:就是无符号的集合。可以看做结构体。


      JVM Class文件格式_第1张图片
      class文件格式
magic

用于标识这个文件是可以被JVM识别的class文件。
0xCAFEBABE

minor_version和major_version

分别表示次版本号和主版本号
Java主版本号从45开始。JDK每个大版本发布,主版本号加1.
高版本JDK可以运行向下兼容以前的版本的Class文件。但不能运行以后的版本。
所以JDK1.7支持的版本号为45.0~51.65535

constant_pool_count和constant_pool

constant_pool开始索引是1,所以constant_pool_count为9的常量池中有8个常量。索引为0的保留。
存储的是字面量和符号引用。

  • 字面量就是常量的概念,主要是文本字符串和final常量。

  • 符号引用包括三大类:
    类和接口的全限定名
    字段的名称和描述符
    方法的名称和描述符

  • 注意:全限定名只是类的全名中的.换成/就可以了。比如一个的全名为com.test.TT则这个类的全限定名就是com/test/TT。

  • 注意:字段和方法的描述符是指字段的数据类型(基本类型和对象)、方法的参数列表、返回值等信息。比如一个String[][]数组,它的描述符为[[java/lang/String;比如一个void inrc()方法的描述符为()inrc;

  • 这里说一句,也就是说代码里出现的任何类的名称、字段名称和描述符、方法的名称和描述符都存在常量池中。下面的信息(this_class/interfaces/fields等)使用到的类名、字段名存的都是指向常量池的引用。理解这点很重要。

access_flags

描述这个类或接口的访问信息。
即这是个类还是接口,是否为public,是否是abstract,是否是final的等。

this_class和super_class和interfaces

这三个字段用于确定这个类的继承关系。

  • this_class表示这个类的全限定名。
  • super_class表示这个类的父类的全限定名。
  • interfaces表示这个类实现了哪些接口。

注意一下:我们发现这些都是u2的,那如何表示全限定名呢?答案是全限定名的字符串存储与常量池中,这里的u2这是表示在常量池中的位置信息。

fields_count和fields
  • 用于描述类中定义的变量。注意这里只是类级别变量和实例级别变量。方法内定义的局部变量这里并不描述。
  • 具体描述了一个变量的访问修饰符(public、private)、是否static、是否final、变量名等信息。
  • 注意:fields不会描述从父类继承的变量。
methods_count和methods
  • 用于描述类中定义的方法。即方法名、方法描述符等信息。
  • 和fields很像,如果父类方法没有被子类重写,则子类的methods中不会出现任何父类的methods的信息。
  • 那存在于方法中的代码去哪儿?
    方法中的代码被编译成字节码存在于attributes中了。
attributes_count和attributes
  • 其实这个位置放在这里是有点问题的。因为fields和methods都会包括自己的attributes集合。
  • 作用就是为了存储一些额外的信息。
    比如如果fields中有一个变量s,定义为final static int s = 123;这样就会在fields中field_info结构体中存在attributes。methods也是类似。方法中的代码被编译成字节码存放于attributes中。

你可能感兴趣的:(JVM Class文件格式)