2.5 运行时数据区域

  java虚拟机定义了多个用于程序执行期间的运行时数据区域。这些数据区域中一些随着java虚拟机的启动而创建,随着虚拟机的退出而销毁。其他的数据区域时和线程相关的。线程相关数据区域随着线程的创建而创建,随着线程的退出而销毁。

2.5.1 pc寄存器

  java虚拟机支持多个线程同时执行。每个线程拥有自己的pc(program counter)寄存器。在任何时刻,一个线程只会执行一个方法,即线程的当前方法。如果执行的方法不是本地(native)方法,pc寄存器包含当前正在执行的虚拟机指令的地址。如果当前线程执行的是本地方法,虚拟机的pc寄存器中的值是未定义的。Java虚拟机的pc寄存器足够保存一个一个特定平台上的returnAddress或本地指针。

2.5.2 java虚拟机栈

  每个线程都拥有一个私有的java虚拟机栈,和线程同时被创建。java虚拟机栈保存的栈是帧(frames)。java虚拟机栈和传统语言(比如c)的栈类似:它保存局部变量和部分结果,并在方法调用和返回中起作用。由于除了栈帧的入栈和出栈,Java虚拟机栈永远不会被直接操作,因此栈帧可以在堆中进行分配。Java虚拟机栈的内存不需要是连续的。

  本规范允许Java虚拟机堆栈具有固定大小或根据计算的需要动态扩展和收缩。如果Java虚拟机栈具有固定大小,则可以在创建该栈时独立选择每个Java虚拟机栈的大小。

  Java虚拟机的一个具体实现可以提供程序员或用户更改Java虚拟机栈初始大小的手段,以及在动态扩展或收缩Java虚拟机栈的情况下,控制最大和最小容量。

  虚拟机栈可能出现以下异常:

  •   如果一个线程需要的虚拟机栈大小超过允许的最大容量时,虚拟机栈将抛出stackOverflowError。
  •   如果java虚拟机栈可以动态扩展,并且当进行扩展时没有申请到足够的内存完成扩展,或者没有足够的内存为新线程创建虚拟机栈,则Java 虚拟机抛出OutOfMemoryError。

2.5.3 Java 堆

  Java虚拟机堆被所有的线程共享。java堆是运行时数据区域,用来分配类实例和数组的内存区域。

  java堆在虚拟机启动时创建。对象的堆存储由自动存储管理系统(称为垃圾收集器)回收;对象永远不会被显式释放。java虚拟机并不假定任何特定的自动存储管理系统类型,存储管理技术会根据实现者的系统需求来选定。堆可以是固定大小,或者根据需要扩展和压缩不需要的容量。堆使用的内存不需要时连续的。

  java堆和虚拟机栈类似,一个具体的实现可以提供开发者或者用户去控制堆的初始大小,也可以去控制一个动态扩展堆的最大和最小容量。

  下面的异常条件和堆有关:

  如果计算需要堆的容量超过了自动存储管理系统能给的最大容量,java虚拟机则抛出OutOfMermoryError。

2.5.4 方法区

  java虚拟机的方法区(method area)被所有Java虚拟机线程共享。方法区类似于传统语言的编译代码的存储区或类似于操作系统进程中的“文本”段。它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,包括类和实例初始化以及接口初始化中使用的特殊方法。

  方法区在虚拟机启动时创建。尽管方法区在逻辑上是堆的一部分,但是简单的实现可以选择不进行垃圾回收和压缩。本规范未规定方法区域的位置或用于管理编译代码的策略。方法区可以是固定大小,或者根据需要扩展和压缩不需要的容量。堆使用的内存不需要时连续的。

  java虚拟机实现可以提供开发者或者用户去控制方法区的初始大小,也可以去控制一个动态扩展方法区的最大和最小容量。

  下面的异常条件和方法区有关:

  如果方法区的没有可用的内存去满足一次内存分配请求,java虚拟机会抛出OutOfMermoryError。

2.5.5 运行时常量池

  运行时常量池(run-time constant pool)是每一个类或者接口对应的class文件中constant_pool表的运行时表示形式。它包含几种常量,从编译时已知的数字的字面量到必须在运行时解析的方法和字段引用。运行时常量池提供类似于传统编程语言的符号表的功能,只是它包含比典型符号表范围更广的数据。

  每个运行时常量池都是分配在java虚拟机的方法区。当Java虚拟机加载类或接口时,将构造类或接口的运行时常量池。

  下面的异常条件和构建一个类或接口的运行时常量池有关:

  当加载一个类或者接口时,如果构建运行时常量池需要的内存超过java虚拟机方法区能够提供的最大容量,虚拟机将抛出OutOfMermoryError。

2.5.6 本地方法栈

  Java虚拟机的实现可以使用传统的栈,俗称“C stacks”,以支持本地方法(native methods)(用Java编程语言以外的语言编写的方法)。当Java虚拟机使用其他语言如C语言来实现java虚拟机指令集的解释器时,也可能用到本地方法栈。如果java虚拟机实现不能加载本地方法,它们自己也不需要依赖传统的栈,则没必要提供本地方法栈。如果支持的话,本地方法栈通常在线程创建的时候按照每个线程分配。

  本规范允许本地方法栈具有固定大小或根据计算的需要动态扩展和收缩。如果本地方法栈具有固定大小,则可以在创建该栈时独立选择每个本地方法栈的大小。

  java虚拟机实现可以提供开发者或者用户去控制本地方法栈的初始大小,也可以去控制一个支持动态扩展的本地方法栈的最大和最小容量。

  下面的异常条件和本地方法栈有关:

  •   如果一个线程需要的本地方法栈的容量超过允许的最大容量,那么虚拟机抛出StackOverflowError。
  •   如果本地方法栈支持动态扩展,当尝试扩展时没有足够的容量可用,或者没有足够的容量去为一个新线程创建一个初始的本地方法栈,java虚拟机抛出OutOfMemoryError。

  

java虚拟机规范(se8)——java虚拟机结构(二)的更多相关文章

  1. java虚拟机规范(se8)——java虚拟机结构(一)

    本文翻译自:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html 第二章 虚拟机结构 本文档描述了一个抽象的虚拟机规范,并不描述 ...

  2. java虚拟机规范(se8)——java虚拟机结构(六)

    2.11 指令集简介 java虚拟机指令由一个字节的操作码,接着时0个或多个操作数组成,操作码描述了执行的操作,操作数提供了操作所需的参数或者数据.许多指令没有操作数只包含一个操作码. 如果忽略异常处 ...

  3. java虚拟机规范(se8)——java虚拟机的编译(四)

    3.12 抛出和处理异常 在程序中使用throw关键字来抛出异常.编译结果很简单. void cantBeZero(int i) throws TestExc { if (i == 0) { thro ...

  4. java虚拟机规范(se8)——java虚拟机的编译(一)

    本文翻译自:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html 第三章 java虚拟机的编译 java虚拟机是设计用来支持ja ...

  5. java虚拟机规范(se8)——java虚拟机结构(三)

    2.6. 栈帧 栈帧用于存储数据和部分结果,同样也用于执行动态链接,返回方法的值和分派异常. 当方法被调用的时候会创建一个新的栈帧.当一个方法调用结束时,它对应的栈帧就被销毁了,不管是正常调用结束还是 ...

  6. java虚拟机规范(se8)——java虚拟机结构(五)

    2.10 异常 java虚拟机中的异常用Throwable类或者它的子类的实例来表示.抛出一个异常会导致立即非本地(an inmediate nolocal)的控制转移,从发生异常的地方跳到处理异常的 ...

  7. java虚拟机规范(se8)——java虚拟机结构(四)

    2.7 对象的表示 java虚拟机并不要求对象满足任何特定的内部结构. 在Oracle的一些Java虚拟机实现中,对类实例的引用是指向句柄的指针,该句柄本身是一对指针:一个指向包含对象方法的表和指向表 ...

  8. java虚拟机规范(se8)——java虚拟机的编译(二)

    3.3 算术运算 java虚拟机通常在操作数栈上进行算术运算(例外情况是iinc指令,它直接增加一个局部变量的值).例如下面的align2grain()方法,它的作用是将int值对齐到2的指定次幂: ...

  9. java虚拟机规范(se8)——java虚拟机的编译(三)

    3.6 接受参数 如果n个参数传给一个实例的方法,按照约定,它们被接受并放在这个新方法创建的栈帧中的局部变量表里,在局部变量表中的序号从1到n.这些参数按照它们传递过来的顺序存放.例如: int ad ...

随机推荐

  1. 【Leetcode】378. Kth Smallest Element in a Sorted Matrix

    Question: Given a n x n matrix where each of the rows and columns are sorted in ascending order, fin ...

  2. 操作系统学习(一)、80x86保护模式内存管理

    整理的不好,凑合着看吧 目录 1.内存及寻址 2.地址变换 3.分段机制 4.分页机制 5.保护 6.去到底部 一.内存及寻址 返回目录 二.地址变换 80X86 从 逻辑地址 到 物理地址 的转换: ...

  3. ES6学习笔记(二):引用数据类型

    Array 新增方法 1.Array.from() 将类数组(dom对象 或 arguments)或set\map对象转换为数组 2.Array.of() 将一组值转换为数组,例如Array.of(3 ...

  4. 微信小程序填坑之旅一(接入)

    一.小程序简介 小程序是什么? 首先“程序”这两个字我们不陌生.看看你手机上的各个软件,那就是程序.平时的程序是直接跑在我们原生的操作系统上面的.小程序是间接跑在原生系统上的.因为它嵌入在微信中,受微 ...

  5. Spring MVC 异步测试

    从spring3.2开始,支持servlet3的异步请求,这对于处理耗时的请求如缓慢的数据库查询是非常有好处的,不至于很快的耗光servlet的线程池,影响可扩展性. 让我们先来了解一下servlet ...

  6. 浅入 dancing links x(舞蹈链算法)

    abastract:利用dancing links 解决精确覆盖问题,例如数独,n皇后问题:以及重复覆盖问题. 要学习dacning links 算法,首先要先了解该算法适用的问题,精确覆盖问题和重复 ...

  7. ctags相关

    ctags相关 首先肯定是下载安装了.这点不用多讲,根据自己的操作系统或者平台,使用相应的包管理工具或者源码编译安装都可以. 下载完之后,在想要使用ctags帮助查找的文件夹(一般是项目的根目录)下输 ...

  8. 【转】spi测试自发自收(中断通信方式)

    1.初始化spi时钟 void spiRccinit(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2Peri ...

  9. 前端学习 -- Css -- 行间距

    在CSS并没有为我们提供一个直接设置行间距的方式,我们只能通过设置行高来间接的设置行间距,行高越大行间距越大.使用line-height来设置行高 .行高类似于我们上学单线本,单线本是一行一行,线与线 ...

  10. IntelliJ IDEA远程调试运行中的JAVA程序/项目

    一.IntelliJ IDEA配置 1.添加一个运行配置(remote项) 2.打开remote项配置对话框 3.远程jvm参数配置提示 4.远程调试的ip地址和端口号,ip就是java项目所在机器i ...