Java 虚拟机结构 (3)

Java 虚拟机实现应当提供给程序员或者最终用户调节 Java 堆初始容量的手段,对于可以动态扩展和收缩 Java 堆来说,则应当提供调节其最大、最小容量的手段。

Java 堆可能发生如下异常情况:

如果实际所需的堆超过了自动内存管理系统能提供的最大容量,那 Java 虚拟机将会抛出一个 OutOfMemoryError 异常。 

4.4 方法区

在 Java 虚拟机中,方法区(Method Area)是可供各条线程共享的运行时内存区域。方法区与传统语言中的编译代码储存区(Storage Area Of Compiled Code)或者操作系统进程 的正文段(Text Segment)的作用非常类似,它存储了每一个类的结构信息,例如运行时常量 池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容、还包 括一些在类、实例、接口初始化时用到的特殊方法。

方法区在虚拟机启动的时候被创建,虽然方法区是堆的逻辑组成部分,但是简单的虚拟机实现可以选择在这个区域不实现垃圾收集。这个版本的 Java 虚拟机规范也不限定实现方法区的内存位置和编译代码的管理策略。方法区的容量可以是固定大小的,也可以随着程序执行的需求动态扩展, 并在不需要过多空间时自动收缩。方法区在实际内存空间中可以是不连续的。 Java 虚拟机实现应当提供给程序员或者最终用户调节方法区初始容量的手段,对于可以动态 扩展和收缩方法区来说,则应当提供调节其最大、最小容量的手段。 方法区可能发生如下异常情况:

如果方法区的内存空间不能满足内存分配请求,那 Java 虚拟机将抛出一个 OutOfMemoryError 异常。

4.5 运行时常量池

运行时常量池(Runtime Constant Pool)是每一个类或接口的常量池(Constant_Pool)的运行时表示形式,它包括了若干种不同的常量:从编译期可知的数值字面量到必须运行 期解析后才能获得的方法或字段引用。运行时常量池扮演了类似传统语言中符号表(Symbol Table)的角色,不过它存储数据范围比通常意义上的符号表要更为广泛。

每一个运行时常量池都分配在 Java 虚拟机的方法区之中,在类和接口被加载到虚拟机后,对应的运行时常量池就被创建出来。

在创建类和接口的运行时常量池时,可能会发生如下异常情况:

当创建类或接口的时候,如果构造运行时常量池所需要的内存空间超过了方法区所能提供的最 大值,那 Java 虚拟机将会抛出一个 OutOfMemoryError 异常。 

4.6 本地方法栈

Java 虚拟机实现可能会使用到传统的栈(通常称之为“C Stacks”)来支持 native 方法 (指使用 Java 以外的其他语言编写的方法)的执行,这个栈就是本地方法栈(Native Method Stack)。当 Java 虚拟机使用其他语言(例如 C 语言)来实现指令集解释器时,也会使用到本地 方法栈。如果 Java 虚拟机不支持 natvie 方法,并且自己也不依赖传统栈的话,可以无需支持本 地方法栈,如果支持本地方法栈,那这个栈一般会在线程创建的时候按线程分配。

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

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

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

五 栈帧

栈帧(Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接 (Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。

栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出 了在方法内未被捕获的异常)都算作方法结束。栈帧的存储空间分配在 Java 虚拟机栈之中,每一个栈帧都有自己的局部变量表(Local Variables,§2.6.1)、操作数栈(Operand Stack)和指向当前方法所属的类的运行时常量池的引用。

局部变量表和操作数栈的容量是在编译期确定,并通过方法的 Code 属性保存及 提供给栈帧使用。因此,栈帧容量的大小仅仅取决于 Java 虚拟机的实现和方法调用时可被分配的 内存。

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

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