JVM规范15-2.5运行时数据区域

FFish 2021年03月31日 103次浏览

Java运行时数据区域(Run-Time Data Areas)

JVM定义了一系列运行时数据区域,提供给程序运行使用。有些区域是在JVM启动时创建,退出时销毁。而线程数据区域时随着线程的启动而创建,线程的退出而销毁。
本文介绍 Oracle HotSpot JVM 运行时内存的一些概念。

jvms152.5runtimedataareas.jpg

程序计数器(PC Register)

JVM支持多线程并发运行,每一个JVM线程都有自己的 pc (program counter) register,即程序计数器。
在任何时间点,每个线程都在执行它的某个方法,称为当前方法(current method),如果这个方法不是 native (指底层C++方法)的,则程序计数器指向目前正在执行的指令。
程序计数器中的值:

  • 当前方法是非native的:程序计数器中存储的是当前指令的地址。
  • 当前方法是native的:程序计数器中存储的是值是undefined

程序计数器足以存储目标机器的地址或native指针。

栈(JVM Stacks)

每个JVM线程在创建时,都会建立一个私有的栈空间,线程栈内的存储单元是栈帧(Frame),后面会介绍。线程栈存储:

  • 局部变量(local variables)
  • 中间变量(partial results)
  • 参与方法调用及返回

JVM的栈空间不必连续,它可以是固定大小,也可以根据需要动态增长和收缩。线程栈的大小除了可以通过JVM参数配置,也可在线程创建时,通过代码设置。

public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
    // ...
}

堆(Heap)

JVM的堆空间是所有线程共享的,所有的类对象和数组都在堆中创建,所有堆中的对象最终都会被垃圾收集器回收。
堆的大小可以是固定的,也可以动态增减,堆空间不必连续。

方法区(Method Area)

方法区存储类结构:

  • 运行时常量池(run-time constant pool)
  • 字段(field)
  • 方法数据
  • 方法和构造函数的代码

运行时常量池(Run-time Constant Pool)

运行时常量池存储的是 class 和 interface 中的常量,包含在编译时确定的数值常量(numeric literals),以及在运行时确定的引用常量。

原生方法栈(Native Method Stacks)

Java 调用原生方法,则会创建原生方法栈。