Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。JVM是为Java字节码定义的一种独立于具体平台的规格描述,是Java平台独立性的基础。

对于字节码指令集不感兴趣,直接看寄存器。

JVM设置了4个最为常用的寄存器。它们是:

pc程序计数器

optop操作数栈顶指针

frame当前执行环境指针

vars指向当前执行环境中第一个局部变量的指针

所有寄存器均为32位。pc用于记录程序的执行。optop,frame和vars用于记录指向Java栈区的指针。

至于为什么只设置4个寄存器,是出于这样的考量:如果虚拟机定义较多的寄存器,便可以从中得到更多的信息而不必对栈或内存进行访问,这有利于提高运行速度。然而,如果虚拟机中的寄存器比实际CPU的寄存器多,在实现虚拟机时就会占用处理器大量的时间来用常规存储器模拟寄存器,这反而会降低虚拟机的效率。

接着看JVM栈结构

Java栈是JVM存储信息的主要方法。当JVM得到一个Java字节码应用程序(.class文件)后,便为该代码中一个类的每一个方法创建一个栈框架,以保存该方法的状态信息。每个栈框架包括以下三类信息:

局部变量,用于存储一个类的方法中所用到的局部变量。vars寄存器指向该变量表中的第一个局部变量;

执行环境,用于保存解释器对Java字节码进行解释过程中所需的信息,包括上次调用的方法、局部变量指针和操作数栈的栈顶和栈底指针,是一个执行一个方法的控制中心

操作数栈,用于存储运算所需操作数及运算的结果。

例如:如果解释器要执行iadd(整数加法),首先要从frame寄存器中找到当前执行环境,而后便从执行环境中找到操作数栈,从栈顶弹出两个整数进行加法运算,最后将结果压入栈顶。

再看JVM垃圾回收堆

Java类的实例所需的存储空间是在堆上分配的。由Java解释器承担为类实例分配空间的工作。Java解释器在为一个实例分配存储空间后,便开始记录对该实例所占用的内存区域的使用。一旦对象使用完毕,便将其回收到堆中。在Java语言中,除了new语句外没有其他方法为一对象申请和分配内存。对内存进行释放和回收的工作是由Java运行系统承担的。

一个大概的JVM内存结构

JVM的每个实例都有一个它自己的方法域和一个堆,运行于JVM内的所有的线程都共享这些区域;当虚拟机装载类文件的时候,它解析其中的二进制数据所包含的类信息,并把它们放到方法域中;当程序运行的时候,JVM把程序初始化的所有对象置于堆上;而每个线程创建的时候,都会拥有自己的程序计数器和Java栈,其中程序计数器中的值指向下一条即将被执行的指令,线程的Java栈则存储为该线程调用Java方法的状态;本地方法调用的状态被存储在本地方法栈,该方法栈依赖于具体的实现。

关于存储方法域,个人理解为与传统语言中的编译后代码或是Unix进程中的正文段类似。它保存方法代码(编译后的java代码)和符号表。在当前的Java实现中,方法代码不包括在垃圾回收堆中,但计划在将来的版本中实现。

再详细说说栈框架的三类信息:局部变量区、运行环境区、操作数区。

局部变量区

每个Java方法使用一个固定大小的局部变量集。它们按照与vars寄存器的字偏移量来寻址。局部变量都是32位的。长整数和双精度浮点数占据了两个局部变量的空间,却按照第一个局部变量的索引来寻址。(例如,一个索引为n的局部变量,如果是一个双精度浮点数,那么它实际占据了索引n和n+1所代表的存储空间)虚拟机规范并不要求在局部变量中的64位的值是64位对齐的。虚拟机提供了把局部变量中的值装载到操作数栈的指令,也提供了把操作数栈中的值写入局部变量的指令。

运行环境区

在运行环境中包含的信息用于动态链接,正常的方法返回以及异常捕捉。

动态链接

运行环境包括对指向当前类和当前方法的解释器符号表的指针,用于支持方法代码的动态链接。方法的class文件代码在引用要调用的方法和要访问的变量时使用符号。动态链接把符号形式的方法调用翻译成实际方法调用,装载必要的类以解释还没有定义的符号,并把变量访问翻译成与这些变量运行时的存储结构相应的偏移地址。动态链接方法和变量使得方法中使用的其它类的变化不会影响到本程序的代码。

正常的方法返回

如果当前方法正常地结束了,在执行了一条具有正确类型的返回指令时,调用的方法会得到一个返回值。执行环境在正常返回的情况下用于恢复调用者的寄存器,并把调用者的程序计数器增加一个恰当的数值,以跳过已执行过的方法调用指令,然后在调用者的执行环境中继续执行下去。

异常捕捉

异常情况在Java中被称作Error(错误)或Exception(异常),是Throwable类的子类,在程序中的原因是:①动态链接错,如无法找到所需的class文件。②运行时错,如对一个空指针的引用。程序使用了throw语句。

当异常发生时,Java虚拟机采取如下措施:

检查与当前方法相联系的catch子句表。每个catch子句包含其有效指令范围,能够处理的异常类型,以及处理异常的代码块地址。

与异常相匹配的catch子句应该符合下面的条件:造成异常的指令在其指令范围之内,发生的异常类型是其能处理的异常类型的子类型。如果找到了匹配的catch子句,那么系统转移到指定的异常处理块处执行;如果没有找到异常处理块,重复寻找匹配的catch子句的过程,直到当前方法的所有嵌套的catch子句都被检查过。

由于虚拟机从第一个匹配的catch子句处继续执行,所以catch子句的顺序是很重要的。因为Java代码是结构化的,因此总可以把某个方法的所有的异常处理器都按序排列到一个表中,对任意可能的程序计数器的值,都可以用线性的顺序找到合适的异常处理块,以处理在该程序计数器值下发生的异常情况。

如果找不到匹配的catch子句,那么当前方法得到一个”未截获异常”的结果并返回到当前方法的调用者,好像异常刚刚在其调用者中发生一样。如果在调用者中仍然没有找到相应的异常处理块,那么这种错误将被传播下去。如果错误被传播到最顶层,那么系统将调用一个缺省的异常处理块。

操作数栈区

机器指令只从操作数栈中取操作数,对它们进行操作,并把结果返回到栈中。选择栈结构的原因是:在只有少量寄存器或非通用寄存器的机器(如Intel486)上,也能够高效地模拟虚拟机的行为。操作数栈是32位的。它用于给方法传递参数,并从方法接收结果,也用于支持操作的参数,并保存操作的结果。

这次到这里,下次仍是一些关于JVM的整理。

java虚拟机的内存模型_JVM(Java虚拟机)内存模型(转载/整理)相关推荐

  1. jvm内存结构_JVM系列之内存结构

    JVM的内存结构大概分为: 堆(Heap):线程共享.所有的对象实例以及数组都要在堆上分配.回收器主要管理的对象. 堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三部分,Eden ...

  2. 运行时错误7内存溢出_JVM运行时内存数据区域

    阅读本文大概需要5分钟 作者:AI乔治出处:https://my.oschina.net/u/3611782/blog/4530512 1 讨论背景 周志明老师写的<深入理解Java虚拟机> ...

  3. jvm内存模型和java内存模型_JVM运行时内存模型综述

    JVM内存模型 JVM分为五个区域:虚拟机栈.本地方法栈.方法区.堆.程序计数器. JVM不同区域的占用内存大小不同,一般情况下堆最大,程序计数器较小. JVM五个区中虚拟机栈.本地方法栈.程序计数器 ...

  4. java 内存日志_JVM深入理解-内存调优与GC日志

    CPU飚高分析 一般可以使用 ps -Lfp pid ps -mp pid -o THREAD, tid, time top -Hp pid [root@redis webapps]# top -Hp ...

  5. jvm内存模型_JVM基础:内存模型

    本篇主要从JVM的内存模型和堆内存详解两个角度整理. 内存模型 JVM中的根据应用使用数据的特性把内存划分为若干个区,根据线程使用的方式可以粗略的分为堆区和栈区,堆区即线程共享的部分(这里的堆区一般指 ...

  6. 【Android 内存优化】Java 内存模型 ( Java 虚拟机内存模型 | 线程私有区 | 共享数据区 | 内存回收算法 | 引用计数 | 可达性分析 )

    文章目录 一. Java 虚拟机内存模型 二. 程序计数器 ( 线程私有区 ) 三. 虚拟机栈 ( 线程私有区 ) 四. 本地方法栈 ( 线程私有区 ) 五. 方法区 ( 共享数据区 ) 1. 方法区 ...

  7. 深入理解JVM虚拟机(十):Java内存模型与多线程

    1. 硬件的效率与缓存一致性 由于存储设备和处理器运算速度之间的存在巨大的差异,现在计算机系统在内存与处理器之间加入高速缓存来作为处理器与内存之间的缓冲.将处理器需要的数据复制到缓存中,让处理器可以快 ...

  8. 深入理解Java虚拟机(一):Java内存模型

    1.Java 虚拟机运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存 ...

  9. Java虚拟机学习(1):体系结构 内存模型

    一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代" ."非堆",  它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内 ...

  10. java 内存模型程序计数器和虚拟机栈

    文章目录 一.程序计数器 二.虚拟机栈 java程序运行过程中会把它所管理的区域划分不同的数据区域,其中包括方法区.虚拟机栈.本地方法栈.堆.程序计数器. 一.程序计数器 程序计数器是一块 较小 的内 ...

最新文章

  1. 较复杂js的书写格式
  2. 超图桌面版下载、安装、使用入门
  3. C语言学习之猴子吃桃问题。猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。
  4. 部署 Node.js 应用以完成服务器端渲染 Server Side Rendering 的性能调优
  5. 输入语句 readline 1006 c#
  6. django 1.8 官方文档翻译: 5-1-1 使用表单
  7. 物联网形势大好,传感器前景可观
  8. 例解List<Map<String, Object>>存放的对象问题
  9. 阶段3 2.Spring_03.Spring的 IOC 和 DI_11 set方法注入
  10. win7 64位专业版读不出来移动硬盘的解决办法
  11. C语言两位八段LED数码管的,简单共阳极数码管电路图大全(五款led数码管电路图详解)...
  12. python自学1.2-运算符和表达式
  13. 三角形形态-非常重要的整理形态
  14. 易语言清理IEcookies 缓存等 可用于IE清理cookies
  15. rtsp开源视频播放器VideoLAN
  16. passwd_pro
  17. k-means均值聚类
  18. Android开发固定app图标大小,Android和IOS开发图标、启动页尺寸
  19. Java SE菜鸟之泛型
  20. Python技能树及Markdown编辑器的测评

热门文章

  1. Python 依赖库
  2. HDU 6428 Problem C. Calculate(积性函数)
  3. 笔记,Vector类模板的基本功能
  4. Educational Codeforces Round 101 (Rated for Div. 2) C. Building a Fence 思维取范围
  5. URAL - 1732 Ministry of Truth--kmp算法的应用(kmp模板)
  6. Link-Cut Tree
  7. Acwing 271. 杨老师的照相排列
  8. 牛客网专题 概率dp
  9. ARC122C-Calculator【乱搞,构造】
  10. CF444C-DZY Loves Colors【线段树,set】