第二章 JVM结构
该文档定义一个抽象机,不描述特定的JVM 实现。
为了正确实现JVM,你需要能够读取class文件格式, 并且能够正确实现规范中的操作。为了不限制实现者的创新,实现细节没有必要写入规范中。例如运行时数据区域内存排列;GC使用的算法;任何JVM指令的内部优化, 比如翻译这些指令为机器码;这些都留给实现者来完成。
class 文件格式
数据类型
JVM操作两种数据类型: 原子类型,引用类型(对象,数组,接口)
原子类型: 数字类型, 布尔类型,返回地址类型(returnAddress)
运行时数据区域
JVM定义了不同的运行时数据区域, 将会在程序执行过程中用到。有些区域JVM启动时创建和销毁。其他的则由线程私有。这些线程区域在在线程创建时创建,线程退出时销毁。
PC寄存器
JVM支持一次执行多个线程。每个线程都有一个PC寄存器。任意时候都会执行一个单个方法, 称为线程当前方法。如果当前方法不是native, PC寄存器包含的是当前将被执行的JVM 指令地址。反之, 则是undefined
JVM栈
线程都有一个私有的JVM栈,线程创建时创建。由Frame组成。与C栈同义,存储的是程序的本地变量和部分结果, 起到一个方法的调用和返回作用。因为JVM栈并不直接操作除了push、pop frames, frames则是在heap分配。不要求连续。
JVM 栈可以定长, 也可动态扩展。StackOverflowError、OutOfMemoryError。
堆(heap)
JVM都有一个所有线程共享的堆,用来存储对象实例和数组。JVM启动时创建,GC回收。对象并不直接回收内存。
方法区
JVM有一个所有线程共享的方法区。用来存储常规语言编译代码或者OS进程对应的text段。存储了每个类结构信息,例如运行时常量池,字段, 方法和构造器或方法指令代码,和一些类,接口初始化时用到的特殊方法。
随JVM启动时创建, 尽管方法区只是heap逻辑的一部分。简单的JVM实现者会选择该区不被GC或者压缩。JVM规范不要求方法区的位置或如何管理编译代码对应使用政策。可定长,可扩展, 不要求连续。
运行时常量池
常量池时单个类、单个接口独有。
原生方法栈
Frames
一个Frame用来存储数据和部分结果,以完成动态链接,返回方法结果,异常分发。方法调用时创建,方法调用完成时销毁,不管方法是否正确调用或者被打断(例如抛出未捕获异常)。它包含了独有的私有变量数组, 独有的操作数栈,一个指向当前类当前方法常量池。