Java 虚拟机结构 (2)

虚拟机中有三种引用类型:类类型(Class Types)、数组类型(Array Types)和 接口类型(Interface Types)。这些引用类型的值分别由类实例、数组实例和实现了某个接口 的类实例或数组实例动态创建。

其中,数组类型还包含一个单一维度(即长度不由其类型决定)的组件类型(Component Type),一个数组的组件类型也可以是数组。但从任意一个数组开始,如果发现其组件类型也是数 组类型的话,继续重复取这个数组的组件类型,这样操作不断执行,最终一定可以遇到组件类型不 是数组的情况,这时就把这种类型成为数组类型的元素类型(Element Type)。数组的元素类型 必须是原始类型、类类型或者接口类型之中的一种。

在引用类型的值中还有一个特殊的值:null,当一个引用不指向任何对象的时候,它的值就 用 null 来表示。一个为 null 的引用,在没有上下文的情况下不具备任何实际的类型,但是有具 体上下文时它可转型为任意的引用类型。引用类型的默认值就是 null。

Java 虚拟机规范并没有规定 null 在虚拟机实现中应当怎样编码表示。

四 运行时数据区 Java

虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机 启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区 域会随着线程开始和结束而创建和销毁。

Java 虚拟机结构

4.1 PC 寄存器

Java 虚拟机可以支持多条线程同时执行(可参考《Java 语言规范》第 17 章),每一条 Java 虚拟机线程都有自己的 PC(Program Counter)寄存器。在任意时刻,一条 Java 虚拟机线程 只会执行一个方法的代码,这个正在被线程执行的方法称为该线程的当前方法(Current Method)。如果这个方法不是 native 的,那 PC 寄存器就保存 Java 虚拟机正在执行的 字节码指令的地址,如果该方法是 native 的,那 PC 寄存器的值是 undefined。PC 寄存器的容 量至少应当能保存一个 returnAddress 类型的数据或者一个与平台相关的本地指针的值。 

4.2 Java 虚拟机栈

每一条 Java 虚拟机线程都有自己私有的 Java 虚拟机栈(Java Virtual Machine Stack),这个栈与线程同时创建,用于存储栈帧(Frames)。Java 虚拟机栈的作用与传统语 言(例如 C 语言)中的栈非常类似,就是用于存储局部变量与一些过程结果的地方。另外,它在 方法调用和返回中也扮演了很重要的角色。因为除了栈帧的出栈和入栈之外,Java 虚拟机栈不会 再受其他因素的影响,所以栈帧可以在堆中分配,Java 虚拟机栈所使用的内存不需要保证是连 续的。

Java 虚拟机规范允许 Java 虚拟机栈被实现成固定大小的或者是根据计算动态扩展和收缩的。如果采用固定大小的 Java 虚拟机栈设计,那每一条线程的 Java 虚拟机栈容量应当在线程创 建的时候独立地选定。Java 虚拟机实现应当提供给程序员或者最终用户调节虚拟机栈初始容量的 手段,对于可以动态扩展和收缩 Java 虚拟机栈来说,则应当提供调节其最大、最小容量的手段。 Java 虚拟机栈可能发生如下异常情况:

如果线程请求分配的栈容量超过 Java 虚拟机栈允许的最大容量时,Java 虚拟机将会抛出一 个 StackOverflowError 异常。

如果 Java 虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是目前无法申请到足够的内存去完成扩展,或者在建立新的线程时没有足够的内存去创建对应的虚拟机栈,那 Java 虚 拟机将会抛出一个 OutOfMemoryError 异常。 

4.3 Java 堆

在 Java 虚拟机中,堆(Heap)是可供各条线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。

Java 堆在虚拟机启动的时候就被创建,它存储了被自动内存管理系统(Automatic Storage Management System,也即是常说的“Garbage Collector(垃圾收集器)”)所管理的各种 对象,这些受管理的对象无需,也无法显式地被销毁。本规范中所描述的 Java 虚拟机并未假设采用什么具体的技术去实现自动内存管理系统。虚拟机实现者可以根据系统的实际需要来选择自动内存管理技术。Java 堆的容量可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需 要过多空间时自动收缩。Java 堆所使用的内存不需要保证是连续的。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwsgy.html