4、第三部分 虚拟机执行子系统-第6章 类文件结构

2021-07-16  本文已影响0人  站得高看得远

无关性的基石

Java虚拟机提供的语言无关性

Class类文件的结构

任何一个Class文件都对应着唯一的一个类或接口的定义信息。但是类或接口并不一定都得定义在文件里(譬如类或接口也可以动态生成,直接送入类加载器中)。

Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符。

魔数与Class文件的版本

每个Class文件的头4个字节被称为魔数(Magic Number),它的唯一作用是确定这个文件是否为 一个能被虚拟机接受的Class文件。

紧接着魔数的4个字节存储的是Class文件的版本号:第5和第6个字节是次版本号(Minor Version),第7和第8个字节是主版本号(Major Version)。


Java Class文件的结构

常量池

十六进制数0x0016,即十进制的22,这就代表常量池中有21项常量,索引值范围为1~21


常量池结构

常量池主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。

  1. 字面量:文本字符串、被声明为final的常量值
  2. 符号引用
    • 被模块导出或者开放的包(Package)
    • 类和接口的全限定名(Fully Qualified Name)
    • 字段的名称和描述符(Descriptor)
    • 方法的名称和描述符
    • 方法句柄和方法类型(Method Handle、Method Type、Invoke Dynamic)
    • 动态调用点和动态常量(Dynamically-Computed Call Site、Dynamically-Computed Constant)


      常量池的项目类型

      常量池的第一项常量,它的标志位(偏移地址:0x0000000A)是0x07,查 表6-3的标志列可知这个常量属于CONSTANT_Class_info类型,此类型的常量代表一个类或者接口的符号引用。


      CONSTANT_Class_info型常量的结构
javap -verbose TestClass
警告: 二进制文件TestClass包含part6.TestClass
Classfile /Users/zengqingjie/privateProject/JVM/src/TestClass.class
  Last modified 2021-6-11; size 352 bytes
  MD5 checksum 29453f5caa2210f993c9393bb32ef5ab
  Compiled from "TestClass.java"
public class part6.TestClass
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#18         // part6/TestClass.m:I
   #3 = Class              #19            // part6/TestClass
   #4 = Class              #20            // java/lang/Object
   #5 = Utf8               m
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               inc
  #12 = Utf8               ()I
  #13 = Utf8               main
  #14 = Utf8               ([Ljava/lang/String;)V
  #15 = Utf8               SourceFile
  #16 = Utf8               TestClass.java
  #17 = NameAndType        #7:#8          // "<init>":()V
  #18 = NameAndType        #5:#6          // m:I
  #19 = Utf8               part6/TestClass
  #20 = Utf8               java/lang/Object
{
  public part6.TestClass();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public int inc();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field m:I
         4: iconst_1
         5: iadd
         6: ireturn
      LineNumberTable:
        line 7: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 12: 0
}
SourceFile: "TestClass.java"

访问标志

访问标志(access_flags),这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract 类型;如果是类的话,是否被声明为final;


访问标志

类索引、父类索引与接口索引集合

字节码指令简介

Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码,Opcode) 以及跟随其后的零至多个代表此操作所需的参数(称为操作数,Operand)构成。由于Java虚拟机采用面向操作数栈而不是面向寄存器的架构,所以大多数指令都不包含操作数,只有一个操作码,指令参数都存放在操作数栈中。

字节码与数据类型

加载和存储指令

加载和存储指令用于将数据在栈帧中的局部变量表和操作数栈间来回传输,这类指令包括:

运算指令

算术指令用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶。大体上运算指令可以分为两种:对整型数据进行运算的指令与对浮点型数据进行运算的指令。不存在直接支持byte、short、char和boolean类型的算术指令,对于上述几种数据的运算,应使用操作int类型的指令代替。所有的算术指令包括:

类型转换指令

类型转换指令可以将两种不同的数值类型相互转换,这些转换操作一般用于实现用户代码中的显式类型转换操作。

Java虚拟机直接支持(即转换时无须显式的转换指令)以下数值类型的宽化类型转换(Widening Numeric Conversion,即小范围类型向大范围类型的安全转换):

对象创建与访问指令

操作数栈管理指令

控制转移指令

方法调用和返回指令

异常处理指令

在Java程序中显式抛出异常的操作(throw语句)都由athrow指令来实现。

而在Java虚拟机中,处理异常(catch语句)采用异常表来完成。

同步指令

Java虚拟机可以支持方法级的同步和方法内部一段指令序列的同步,这两种同步结构都是使用管程(Monitor,更常见的是直接将它称为“锁”)来实现的。

同步一段指令集序列通常是由Java语言中的synchronized语句块来表示的,Java虚拟机的指令集中 有monitorenter和monitorexit两条指令来支持synchronized关键字的语义,正确实现synchronized关键字需要Javac编译器与Java虚拟机两者共同协作支持

源自书籍:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)-周志明

上一篇 下一篇

猜你喜欢

热点阅读