本笔记参考的是JVMS14
本节内容接着上一篇文章——Inside the Java Virtual Machine学习笔记8。之所以中途换成JVMS是因为发现Inside the Java Virtual Machine书中的内容已与现在版本的jvm有较多出入。
运行时数据区域
PC寄存器(The Program Counter Register)
每个 Java 虚拟机线程都有自己的 pc(程序计数器)寄存器。在任何时候,每个 Java 虚拟机线程都在执行单个方法的代码,即该线程的当前方法。如果该方法不是本机方法,则 pc 寄存器包含当前正在执行的 Java 虚拟机指令的地址。如果线程当前正在执行的方法是native的,那么Java虚拟机的pc寄存器的值是未定义的。
Java虚拟机栈
Java虚拟机栈由栈帧组成,栈帧包含一个方法的调用信息(局部变量,方法出口等)。每个 Java 虚拟机线程都有一个私有的 Java 虚拟机栈,与线程同时创建。 Java 虚拟机栈类似于 C 语言的栈:它保存局部变量和部分结果,并在方法调用和返回中发挥作用。Java 虚拟机栈的内存不需要是连续的。
Java 虚拟机堆栈可以具有固定大小或根据计算要求动态扩展和收缩。如果 Java 虚拟机堆栈具有固定大小,则每个 Java 虚拟机堆栈的大小可以在创建堆栈时独立选择。一个具体Java 虚拟机的实现可以让程序员或用户控制 Java 虚拟机堆栈的初始大小,以及在动态扩展或收缩 Java 虚拟机堆栈的情况下,控制最大和最小值。
Java虚拟机栈有以下两种异常情况:
1. StackOverflowError 如果线程中的计算需要的栈的大小大于允许的栈大小。
2. OutOfMemoryError 如果Java虚拟机栈容量允许动态扩展,当扩展时无法申请到足够的内存。
堆
堆在所有虚拟机线程之间共享。堆为所有类实例和数组分配内存。
堆是在虚拟机启动时创建的,对象的堆存储由GC进行回收,对象永远不会被显示释放。
Java虚拟机假设没有特定类型的自动存储管理系统,可以根据实现者的系统要求选择存储管理技术。堆可以是固定大小的,也可以根据计算的需要进行扩展,如果不需要更大的堆,则可以收缩。堆的内存不需要是连续的。
如果计算需要的堆比自动存储管理系统可用的更多,Java 虚拟机会抛出 OutOfMemoryError。
方法区
Java 虚拟机有一个在所有 Java 虚拟机线程之间共享的方法区。它存储每个类的结构,例如运行时常量池、字段和方法数据,以及方法和构造函数的代码,包括类和接口初始化以及实例初始化中使用的特殊方法。
方法区是在虚拟机启动时创建的。尽管方法区在逻辑上是堆的一部分,但简单的实现可能会选择不进行垃圾收集或压缩它。JVM规范并不要求方法区的实现细节。
运行时常量池
运行时常量池是方法区的一部分。class文件中除了有类的版本,字段,方法,接口等信息外,还有一项信息是常量池表,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
常量池中的条目由索引引用,很像数组的元素。因为它包含对一个类型使用的所有类型、字段和方法的符号引用,所以常量池在 Java 程序的动态链接中起着核心作用。
本地方法栈
与虚拟机栈发挥的作用相似,为虚拟机使用本地方法服务。java虚拟机的实现若不加载本地方法并且本身不依赖于传统栈则不需要提供本地方法栈。