Run Time Data Area 运行时数据区

Java虚拟机定义了在程序执行期间使用的各种运行时数据区域。其中一些数据区域是在Java Virtual上创建的
机器启动,只有在Java虚拟机退出时才会被销毁。其他数据区域是每个线程的。每个线程的数据区域在线程创建时创建,在线程退出时销毁。

PC Register PC寄存器

  • Java虚拟机可以支持一次执行多个线程。每个Java虚拟机线程都有自己的pc(程序计数器)寄存器。
  • 存放指令位置(非本地方法指令)

    JVM Stacks

  • 每一个JVM线程都有一个JVM Stack,线程创建时创建。

  • JVM 栈存放栈帧(Frame)
  • JVM Satck 和大多数语言(如C语言)的栈一样,存放方法计算需要的局部变量、中间结果。
  • JVM规范规定,JVM Stack可以是固定大小,也可以动态扩容
  • 如果线程中的计算需要的JVM Stack大小不足,JVM抛出 StackOverflowError
  • JVM Stack可动态扩容,但是没有内存用于扩容或创建新的线程,JVM抛出OutOfMemoryError

    Heap

  • Heap(堆)存放多线程共享的信息(对象实例、数组等)

  • 虚拟机启动时Heap创建
  • Heap大小可以是固定的,也可以动态扩容收缩(可以设置堆的初始大小、动态扩容还可以设置对小、最大大小)
  • Haep内存可以是不连续的
  • Heap内存不足时,JVM抛出OutOfMemoyError

    Method Area

  • Method Area被多JVM线程共享

  • Method存储每个类的结构,如运行时常量池、字段和方法数据,以及方法和构造函数的代码,包括在类、实例初始化和接口初始化中使用的特殊方法(
  • Method Area在JVM启动时创建
  • Method Area 逻辑上是Heap的一部分,但是jdk1.7之前不会被GC,jdk1.8之后会被FGC
  • Method Area可以是固定大小,也可以动态扩容和收缩
  • Method Area内存不需要连续
  • jdk1.8之前,Method Area实现为Permanent Generation,jdk1.8及之后为Meta Space
  • Method Area内存不足,抛出OutOfMemoryError

    Run_Time Constant Pool

  • Run_Time Constant Pool是每个类或接口的Class文件Constant_pool表运行时的表现

  • Run_Time Constant Pool包含几种类型的常量,从编译时已知的数字字面值到必须在运行时解析的方法和字段引用。
  • Run_Time Constant Pool使用方法区(Method Area)分配的
  • Run_Time Constant Pool在JVM加载类或接口时创建
  • 加载类或接口时,如果需要的Run_Time Constant Pool内存不足,JVM抛出OutOfMemoryError

    Native Method Stacks

  • Native Method Stacks通常在创建每个线程时分配给每个线程

  • Native Method Stacks用于存储native Method
  • Native Method Stacks可以是固定大小,也可以动态扩容收缩
  • 计算中,Native Method Stacks内存不足,JVM抛出StackOverflowError
  • Native Method Stacks动态扩容,但是内存不足,或者没有足够的内存为新线程创建初始的本机方法堆栈,那么JVM抛出OutOfMemoryError

    Frames 栈帧

    image.png

  • 一个框架用于存储数据和部分结果,以及执行动态链接、返回值的方法和分派异常。

  • 每个方法调用时会创建一个栈帧(frame),方法调用结束或抛出异常时该栈帧(frame)销毁
  • 栈帧(Frame)是从每个线程的JVM Stacks中分配
  • 每个frame都有自己的局部变量表(local variables),操作数堆栈(operand stack),以及当前方法类的运行时常量池的引用

    Local Variables 局部变量表

  • 每个栈帧都有自己的局部变量表,一个局部变量可以保存byte、short、int、char、float、boolean、reference、returnAnddress;一对局部变量可以存储long、double

  • 局部变量通过索引来管理,从0开始。对于long、double需要占2个索引。

image.png

Operand Stacks 操作数栈

  • 每个栈帧(Fame)都有一个LIFO(last-in-first-out,后进先出)的操作数栈
  • operand stacks 创建时为空,JVM指令可以把局部变量表、或者常量压入operand stacks,也可以操作操作数栈的内容

    Dynamic Linking 动态链接

  • 每个栈帧都有对Run_time Constant Pool的引用,以支持动态链接。

  • 方法的类文件代码引用通过符号引用要调用的方法和要访问的变量。动态链接将这些符号方法引用转换为具体的方法引用,根据需要加载类来解析尚未定义的符号,并将变量访问转换为与这些变量的运行时位置相关联的存储结构中的适当偏移量。
  • 参考文档:https://blog.csdn.net/qq_41813060/article/details/88379473

    Method Invocation Completion

  • 方法调用可正常结算,也可以是抛出异常

  • 方法结束返回结果或异常

    返回地址

    Specail Methods

    ,创建对象实例只有通过JVM指令 invokespecial 调用能在未初始化的类实例上被调用。
    ,一个类或接口最多只有一个类或接口的初始化方法,并通过调用该方法进行初始化

JVM指令

Java虚拟机指令集中的类型支持image.png

Load and Store Instructions 加载指令、存储指令

  • 将局部变量加载到操作数堆栈:
    • iload
    • iload_
    • lload
    • lload_
    • fload
    • fload_
    • dload
    • dload_
    • aload
    • aload_
  • 将操作数堆栈中的值存储到局部变量中
    • istore
    • istore_
    • lstore
    • lstore_
    • fstore
    • fstore_
    • dstore
    • dstore_
    • astore
    • astore_
  • 将一个常量加载到操作数堆栈
    • bipush
    • sipush
    • ldc
    • ldc_w
    • ldc2_w
    • aconst_null
    • iconst_m1
    • iconst_
    • lconst_
    • fconst_
    • dconst_
  • 使用更宽的索引或更大的直接操作数访问更多局部变量

    • wide

      Arithmetic Instructions 运算指令

      运算指令通常是操作数堆栈上两个值的函数,将结果推回到操作数堆栈。主要有操作整数和浮点数两类运算指令。没有直接对byte、short、char、boolean类型的操作指令,对于这这些类型的数据操作,转换为int类型进行操作。
  • Add 加法操作

    • iadd
    • ladd
    • fadd
    • dadd.
  • Subtract 减法操作
    • isub
    • lsub
    • fsub
    • dsub.
  • Multiply 乘法操作
    • imul
    • lmul
    • fmul
    • dmul.
  • Divide 除法操作
    • idiv
    • ldiv
    • fdiv
    • ddiv.
  • •Remainder 取余操作
    • irem
    • lrem
    • frem
    • drem.
  • Negate 取反操作
    • ineg
    • lneg
    • fneg
    • dneg
  • •Shift 移位caozuo
    • ishl
    • ishr
    • iushr
    • lshl
    • lshr
    • lushr
  • •Bitwise OR 按位或操作
    • ior
    • lor
  • •Bitwise AND 按位与操作
    • iand
    • land
  • Bitwise exclusive OR 按位异或操作
    • ixor
    • lxor
  • Local variable increment 变量自增操作
    • iinc
  • Comparison 比较操作
  • dcmpg
  • dcmpl
  • fcmpg
  • fcmpl
  • lcmp

Type Conversion Instructions 类型转换指令

  • int 转换为long、float、double
    • i2l
    • i2f
    • i2d
  • long 转为为float、double
    • l2f
    • l2d
  • float 转换为 double
    • f2d
  • int 转换为byte、short、char
    • i2b
    • i2s
    • i2c
  • long 转换为 int
    • l2i
  • float 转换为int、long
    • f2i
    • f2l
  • double 转换为int、long、float

    • d2i
    • d2l
    • d2f

      Object Creation and Manipulation 对象创建和操作指令

  • 创建对象

    • new
  • 创建数组
    • newarray
    • anewarray
    • multianewarray
  • 类的访问字段(静态字段,称为类变量)和类实例的字段(非静态字段,称为实例变量)
    • getstatic
    • putstatic
    • getfield
    • putfield.
  • 将局部变量表的元素加载到操作数堆栈中
    • baload
    • caload
    • saload
    • iaload
    • laload
    • faload
    • daload
    • aaload.
  • 将操作数堆栈中的值存储为在局部变量表中
    • bastore
    • castore
    • sastore
    • iastore
    • lastore
    • fastore
    • dastore
    • aastore
  • 获取数组长度
    • arraylength
  • 检查类实例或数组的属性

    • instanceof
    • checkcast

      操作数堆栈管理指令

  • 直接操作操作数堆栈

    • pop
    • pop2
    • dup
    • dup2
    • dup_x1
    • dup2_x1
    • dup_x2
    • dup2_x2
    • swap

      转移控制指令

  • 条件转移

    • ifeq
    • ifne
    • iflt
    • ifle
    • ifgt
    • ifge
    • ifnull
    • ifnonnull
    • if_icmpeq
    • if_icmpne
    • if_icmplt
    • if_icmple
    • if_icmpgt
    • if_icmpge
    • if_acmpeq
    • if_acmpne
  • 复合条件分支
    • tableswitch
    • lookupswitch
  • 无条件转移

    • goto
    • goto_w
    • jsr
    • jsr_w
    • ret

      方法调用和返回指令

  • invokevirtual

调用对象的实例方法,在(虚拟的)对象类型

  • invokeinterface

调用接口方法,搜索由特定运行时对象实现的方法以找到适当的方法

  • invokespecail

调用需要特殊处理的实例方法,无论是实例初始化方法、私有方法还是超类方法

  • invokestatic

调用命名类中的类(静态)方法

  • invokedynamic

调用方法,该方法是绑定到invokedynamic指令的调用站点对象的目标

抛出异常

  • athrow

    同步 Synchronization

  • monitor

    • 同步方法在运行时常量池的method_info结构中由ACC_SYNCHRONIZED标志区分
    • 当调用设置了ACC_SYNCHRONIZED的方法时,执行线程进入监视器,完成调用退出监视器
    • 在执行线程拥有监视器的期间,其他线程不能进入它。如果在调用同步方法期间抛出异常,而同步方法没有处理该异常,则在同步方法重新抛出异常之前自动退出该方法的监视器。