jvm学习笔记(1)class文件

 

  • 简述
  • class文件是什么?稍微接触过java的同学都会说:就是java源文件编译后的.class文件。这句话虽然对,但是不够准确。其他语言,例如scala,jruby等,都可以编译出class文件。class文件是能被jvm识别和运行的一种文件格式。它是八位的二进制流文件。今天就跟大家一起学习class文件的格式

  • 整体结构
  • 用ultraedit等工具打开class文件,看到的都是二进制。首先要了解哪几位代表什么标志?这里用u1,u2,u4,u8,代表属性占用多少个字节。

    格式,如下
    类型 名称 数量
    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 interface_count
    u2 fields_count 1
    field_info fields fields_count
    u2 methods_count 1
    method_info methods methods_count
    u2 attributes_count 1
    attributes_inof attributes attributes_count

    详细
    看了上面的大体介绍,明白了class文件的基本结构后,我们就逐一来介绍各个部分。

  • 1.magic
  • 前四个字节 0xCAFEBABE,就是代表该文件格式是class文件了。出于安全考虑,class文件不是以文件后缀名来识别

  • 2.minor_version 和 major_version
  • jvm只能处理低于或者等于它版本后的class文件。所以class文件首先要定义自己的版本,才能让jvm判断能否执行。版本号的描述一般都是 major_version.minor_version。各个版本号代表的数值可以去查看jvm说明书

  • 3.constant_pool
  • 常量池,里面包含了类和接口相关的常量,比如final变量值、类名、方法名等。接下来定义方法等信息时,就给一个索引去常量池寻找相关的信息。这个索引是从1开始的。为什么不是0开始?其实是有的,只不过被当做特殊用途了。所以constant_pool_count是将索引0也计入在内。每个常量值都有一个u1大小的标志。如下:

    入口类型 标志值 描述
    CONSTANT_Utf8 1 UTF-8编码的Unicode字符串
    CONSTANT_Integer 3 int类型字面量
    CONSTANT_Float 4 float类型字面值
    CONSTANT_Long 5 long类型字面量
    CONSTANT_Double 6 double类型字面量
    CONSTANT_Class 7 对一个类或者接口的符号引用
    CONSTANT_String 8 String类型字面量
    CONSTANT_Fieldref 9 对一个字段的符号引用
    CONSTANT_Methodref 10 对一个类中声明的方法的符号引用
    CONSTANT_InterfaceMethodRef 11 对一个接口中声明的方法的符号引用
    CONSTANT_NameAndType 12 对一小字段或者发放的部分符号引用

    常量池中包括了:字面量;类和接口的全限定名;字段的名称和描述符;方法的名称和描述符。字段飞描述符就是字段类型的字符串。方法的描述符是方法返回值和参数的数量,顺利和类型的描述。jvm只是从常量池中获得符号引用,然后在运行时解析引用项的实际地址。

  • 4.access_flags
  • 顾名思义就是类或者接口的访问修饰符,例如public abstract等。每个访问修饰符用一位二进制位来表示。access_flags就是所有的访问修饰符“与”关系。//todo 访问修饰符的定义

  • 5.this_class
  • 类的基本信息。包括两个字节,是常量池的一个CONSTANT_Class_info表的索引。该表结构包括两部分:tag和name_index。tag值等于该索引值。通过name_index,我们又可以在常量池中找到一个对应的CONSTANT_Utf8_info表。Utf8表结构包括三部分:tag(等于utf8表的索引值);length和byte(字符串内容)

  • 6.super_class
  • 父类的相关信息。格式跟this_class一样。每个对象只有一个父类(单继承)。而object类的super_class为0

  • 7.interfaces_count和interface
  • 所实现的接口的相关信息。每个接口都由一个索引指向常量池中的一个CONSTANT_Class_info

  • 8.field_count和fields
  • 字段的相关信息。每个字段都由一个索引指向常量池的一个field_info。这里不会出现父类的field。但可能出现一些代码中没有定义的字段,是编译器额外添加的。例如,内部类中,会有一个外部类的实例

  • 9.methods_count和methods
  • 关于方法的相关信息,每个方法都有一个索引指向常量池的method_info表

  • 10.attributes_count和attributes
  • 类或接口所定义的属性的基本信息。每个属性都由一个索引指向常量池的attribute_info。属性在很多地方都出现,比如在field_info中出现描述与字段相关的属性信息。在顶层ClassFile中有两种属性-SourceCode和InnerClass

  • 11.几个常用到的概念
  • 全限定名-把类的全名用.替换成/

    简单名称-方法或者字段的名称,不包括任何的修饰符

    描述符号
    比较复杂.先来看类型的定义.B-byte,C-char,D-double,F-float,I-int,J-long,S-short,Z-boolean,V-void,L对象全限定名-对象类型.
    描述数组,用前置的”[“来表示,有几维就加多少个”[“.

    字段描述符=数组描述符+类型描述符
    方法描述符=左括号+参数描述符(按定义的顺序)+右括号+返回值描述符

  • 总结:
  • 跟大家一起稍微了解了class文件的结构,明白了它的大概组织结构。篇幅有限,本来应该找个最简单的helloworld程序的字节码来一一说明的。详细例子,大家可以参考以下书籍

  • 参考资料
  • 1.深入java虚拟机
    2.深入理解java虚拟机

    更多关于jvm的内容欢迎访问 www.iamcoding.com

    你可能感兴趣的:(java,jvm)