Java虚拟机-Class文件结构之访问标志、类索引、父类索引、接口索引集合

1 实例代码

接下来通过下面示例class文件示例来看了解JAVA虚拟机规范如何定义Class文件结构:

示例代码

public class TestClass {

    private int m;

    public int inc() {
        return m + 1;
    }
}

示例Class文件

image

2 访问标志(access_flags)

按照Java虚拟机规范紧跟在常量池表后面2个字节(u2)用来表示Class访问标志(access_flags),这个标志主要用于识别一些类或者接口层次的访问信息,主要包括:

  • 这个Class是类还是接口;
  • 是否定义为public类型;
  • 是否定义abstract类型;
  • 如果是类的话是否被声明为final;

Java虚拟机规范定义访问标志

image

示例中访问标志

访问标志2个字节来描述,对应16进制0x0021。而示例代码中TestClass是一个普通Java类,被public关键字修饰,因此它的ACC_PUBLIC、ACC_SUPER标志应为真,其余的标志位为假,它的 access_flags 值应为:0x0001|0x0020 = 0x0021,和示例值匹配。

image

对照源代码中定义类名称TestClass仅被public修饰

public class TestClass {

    private int m;

    public int inc() {
        return m + 1;
    }
}

10 类名,父类名,接口个数,接口名称

  • 类名:用来表示类的全限定名

  • 父类名:用来表示父类的全限定名

  • 类接口个数:表示类的接口的数量

  • 接口名称:表示类的接口名称

示例在Class文件2进制描述位置

  • 类名用2位字节(u2)来描述,对应16进制0x0003,即十进制的3,3是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Class_info类型的常量(下标#3),CONSTANT_Class_info类型常量其值转换为整数20,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#20),字符串值为"jvm/TestClass"。
  • 父类名用2位字节(u2)来描述,对应16进制0x0004,即十进制的4,4是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Class_info类型的常量(下标#4),CONSTANT_Class_info类型常量其值转换为整数21,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#21),字符串值为"java/lang/Object"。
  • 类接口数量用2位字节(u2)来描述,对应16进制0x0000,即十进制的0,表示当前类没有实现接口。因此Class文件中不存在接口名称描述。

image

javap常量池结果

Constant pool:
   #1 = Methodref          #4.#18         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#19         // jvm/TestClass.m:I
   #3 = Class              #20            // jvm/TestClass
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               m
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Ljvm/TestClass;
  #14 = Utf8               inc
  #15 = Utf8               ()I
  #16 = Utf8               SourceFile
  #17 = Utf8               TestClass.java
  #18 = NameAndType        #7:#8          // "<init>":()V
  #19 = NameAndType        #5:#6          // m:I
  #20 = Utf8               jvm/TestClass
  #21 = Utf8               java/lang/Object

对照源代码中定义类名称TestClass,继承父类java/lang/Object,没有实现接口

public class TestClass {

    private int m;

    public int inc() {
        return m + 1;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容