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

1 实例代码

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

示例代码

public class TestClass {

    private int m;

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

示例Class文件

Java虚拟机-Class文件结构之访问标志、类索引、父类索引、接口索引集合_第1张图片
image

2 访问标志(access_flags)

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

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

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

Java虚拟机-Class文件结构之访问标志、类索引、父类索引、接口索引集合_第2张图片
image

示例中访问标志

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

Java虚拟机-Class文件结构之访问标志、类索引、父类索引、接口索引集合_第3张图片
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文件中不存在接口名称描述。

Java虚拟机-Class文件结构之访问标志、类索引、父类索引、接口索引集合_第4张图片
image

javap常量池结果

Constant pool:
   #1 = Methodref          #4.#18         // java/lang/Object."":()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               
   #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          // "":()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;
    }
}

你可能感兴趣的:(Java虚拟机-Class文件结构之访问标志、类索引、父类索引、接口索引集合)