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

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内存结构

0d759b31286cefd98536e6b4de15f8be.png

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的整理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328488.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如果你也会C#,那不妨了解下F#(6):面向对象编程之“类”

前言 面向对象的思想已经非常成熟,而使用C#的程序员对面向对象也是非常熟悉,所以我就不对面向对象进行介绍了,在这篇文章中将只会介绍面向对象在F#中的使用。 F#是支持面向对象的函数式编程语言,所以你用C#能做的,用F#…

新华三

百度 新华三 笔试题目 http://www.663395.net/xxs163090/ https://wenku.baidu.com/view/f61a1161ae1ffc4ffe4733687e21af45b307fe7d.html https://blog.csdn.net/qq_36562999/article/details/81436356 https://blog.csdn.net/kyyee/article/details/78090954?locationNum4&…

java面试题及答案(基础题122道,代码题19道)

转载自 java面试题及答案(基础题122道,代码题19道) JAVA相关基础知识 1、面向对象的特征有哪些方面 1.抽象:  抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打…

java aqs详解_Java AQS底层原理解析

AQS底层原理AQS(AbstractQueuedSynchronizer)是一个抽象同步队列,JUC(java.util.concurrent)中很多同步锁都是基于AQS实现的。AQS的基本原理就是当一个线程请求共享资源的时候会判断是否能够成功操作这个共享资源,如果可以就会把这个共享资源设置为锁定状…

在.NET Core程序中设置全局异常处理

以前我们想设置全局异常处理只需要这样的代码: 1 AppDomain currentDomain AppDomain.CurrentDomain;2 currentDomain.UnhandledException new UnhandledExceptionEventHandler(MyExceptionHandler); 但是在.NET Core中并没有AppDomain的相关实现,至少…

matlab 画柱状图

data [0.1869, 0.1900, 0.1878, 0.1847]; b bar(data); ch get(b,children); set(gca,XTickLabel,{非加权聚类欧氏距离类比,非加权聚类马氏距离类比,加权聚类欧氏距离类比,加权聚类马氏距离类比}) set(ch,FaceVertexCData,[1 1 1;1 1 1;1 1 1;1 1 1;])

java释放线程资源_Java线程之释放锁,释放资源,释放CPU

多线程中的wait与sleep到底谁释放了锁首先,多线程中会使用到两个延迟的函数,wait和sleep。wait是Object类中的方法,而sleep是Thread类中的方法。sleep是Thread类中的静态方法。无论是在a线程中调用b的sleep方法,还是b线程中调用a的…

经典的Java基础面试题集锦

转载自 经典的Java基础面试题集锦问题:如果main方法被声明为private会怎样? 答案:能正常编译,但运行的时候会提示”main方法不是public的”。 问题:Java里的传引用和传值的区别是什么? 答案:传…

聚类中心选取

https://blog.csdn.net/zhihaoma/article/details/48649489 https://www.cnblogs.com/dudumiaomiao/p/5839905.html

Vue.js先入个门看看

使用vue.js原文介绍&#xff1a;Vue.js是一个构建数据驱动的web界面库。Vue.js的目标是通过尽可能简单的API实现响应式数据绑定和组合的视图组件。vue.js上手非常简单&#xff0c;先看看几个例子&#xff1a; 例一&#xff1a;Helloworld html代码&#xff1a; <div id"…

java path 注解_@PathVariable注解的使用和@Requestparam

一、 PathVariablePathVariable这是一个路径映射格式的书写方式注解&#xff0c;在类映射路径的后加上/{对应方法参数中属性PathVariable("code")中的code}&#xff0c;SuppressWarnings({ "unchecked", "rawtypes" })RequestMapping(value &qu…

近5年133个Java面试题 你会几个?

https://blog.csdn.net/fireblue1990/article/details/73695121 http://www.ablanxue.com/shtml/201608/33470_1.shtml

精选30道Java笔试题解答

转载自 精选30道Java笔试题解答 1. 下面哪些是Thread类的方法&#xff08;&#xff09; A start() B run() C exit() D getPriority() 答案&#xff1a;ABD 解析&#xff1a;看Java API docs吧&#xff1a;http://docs.oracle.com/javase/7/docs/ap…

.NET Core 1.0.1 发布了

今天微软发布了 .NET Core 1.0.1&#xff0c;这是 .NET Core 1.0 的首个微软长期支持更新&#xff0c;同时发布的还有 ASP.NET Core 1.0.1 与 Entity Framework Core 1.0.1。 .NET Core 1.0.1 中的主要更新与 bug 修复&#xff1a; Segfaults on Linux 4.6 – coreclr 6016; co…

java this用法_java中this用法小结

Java关键字this只能用于方法方法体内。当一个对象创建后&#xff0c;Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针&#xff0c;这个指针的名字就是this。因此&#xff0c;this只能在类中的非静态方法中使用&#xff0c;静态方法和静态的代码块中绝对不能出现this,并且…

第1步 新建spring+springmvc+mybatis项目 每步都有 讲解 巨详细

Idea2017部署项目到tomcat时没有artifacts解决办法 2017年12月01日 23:16:22 剑胜 阅读数&#xff1a;10342 在Idea2017中想部署maven构建的项目到tomcat容器中时&#xff0c;需要配置Deployment属性&#xff0c;选择war或者war exploded的发布方式。而要进行这个配置首先要点…

Java 集合系列04之 fail-fast总结

转载自 Java 集合系列04之 fail-fast总结概要 前面&#xff0c;我们已经学习了ArrayList。接下来&#xff0c;我们以ArrayList为例&#xff0c;对Iterator的fail-fast机制进行了解。内容包括&#xff1a;&#xff1a;1 fail-fast简介2 fail-fast示例3 fail-fast解决办法4 fai…

Vue.js说说组件

什么是组件&#xff1a;组件是Vue.js最强大的功能之一。组件可以扩展HTML元素&#xff0c;封装可重用的代码。在较高层面上&#xff0c;组件是自定义的元素&#xff0c;Vue.js的编译器为它添加特殊功能。在有些情况下&#xff0c;组件也可以是原生HTML元素的形式&#xff0c;以…

java 内存快照怎么看_jvm内存快照dump文件太大,怎么分析

1、场景通常&#xff0c;使用eclipse的mat图形化工具打开dump的时候都会内存溢出.对于比较小的dump&#xff0c;eclipse可以打开&#xff0c;但一旦dump文件太大&#xff0c;eclipse就有点束手无策。这时候怎么办呢&#xff1f;可以使用linux下的mat&#xff0c;既Memory Analy…

第3步 (请先看第2步再看第3步) 新建完spring+springmvc+mybatis项目 需要推送gitee仓库进行管理 巨详细

idea中Terminal终端无法执行GIT命令&#xff1a; touch README.md问题解决 解决方法二&#xff1a; ◆更改路径即可 Git\bin\bash.exe 或 Git\bin\sh.exe 然后重新启动idea即可 ********************88注意&#xff1a;每次更改完成后需要重新启动IDEA****************** 记…