JVM规范描述的是一种抽象化的虚拟机的行为,而不是任何一种广泛使用的虚拟机实现。
要去“正确地”实现一台Java虚拟机,其实并不像大多数人所想的那样高深和困难——只需要正确读取class文件中每一条字节码指令,并且能正确执行这些指令所蕴含的操作即可。
所有在虚拟机规范之中没有明确描述的实现细节,都不应成为虚拟机设计者发挥创造性的牵绊,设计者可以完全自主决定所有规范中不曾描述的虚拟机内部细节,
例如,运行时数据区的内存如何布局,选用哪种垃圾收集算法,是否要对虚拟机字节码指令进行一些内部优化操作(如使用即时编译器把字节码编译为机器码)。

1 Class文件格式

编译后被Java虚拟机所执行的代码使用了一种平台中立(不依赖于特定硬件及操作系统)的二进制格式来表示,并且经常(但并非绝对)以文件的形式存储,因此这种格式称为class文件格式。
class文件格式中精确地定义了类与接口的表示形式,包括在平台相关
的目标文件格式中一些细节上的惯例,例如字节序( byte ordering)等。

2 数据类型

与Java程序语言中的数据类型相似,Java虚拟机可以操作的数据类型可分为两类:原始类型(primitivetype,也经常翻译为原生类型或者基本类型)和引用类型(reference type)
与之对应,也存在原始值( primitive value)和引用值(reference value)两种类型的数值,它们可用于变量赋值、参数传递、方法返回和运算操作。
Java虚拟机是直接支持对象的。这里的对象可以是指动态分配的个类的实例,也可以指某个数组。虚拟机中使用reference类型来表示对某个对象的引用。关于reference类型的值,你可以想象成指向对象的指针。每一个对象都可能存在多个指向它的引用,对象的操作、传递和检查都通过引用它的reference类型的数据来进行

3 原始类型与值

3.1 数值类型,boolean类型和returnAddress类型

Java虚拟机所支持的原始数据类型包括数值类型(numeric type)、boolean类型和returnAddress类型三类。
数值类型又分为整数类型(integral type)和浮点类型(floating-point type,)两种。
整数类型包括:
口byte类型:值为8位有符号二进制补码整数,默认值为零。
口short类型:值为16位有符号二进制补码整数,默认值为零。
口int类型:值为32位有符号二进制补码整数,默认值为零。
口long类型:值为64位有符号二进制补码整数,默认值为零。
口char类型:值为使用16位无符号整数表示的Unicode码点,以UTF-16编码,默认值为Unicode的null码点( ‘\u0000’)。
浮点类型包括:
口float类型:单精度
口double类型:值为双精度浮点数集合中的元素
boolean类型的值为布尔值true和false,默认值为false。
returnAddress类型是指向某个操作码(opcode)的指针,此操作码与Java虚拟机指令相对应。在虚拟机支持的所有原始类型中,只有returnAddress类型是不能直接与Java语言的数据类型相对应的。

3.2 整数类型的取值范围

Java虚拟机中的整数类型的取值范围如下:
口对于byte类型,取值范围是-128~127 包括-128和127
口对于short类型-2’5~ 2’5-1
口对于int类型,取值范围是-2’31~ 2’31-1
口对于long类型,取值范围是-2’63~ 2’63-1
口对于char类型,取值范围是O~65535,包括O和65535

3.3 returnAddress类型和值

returnAddress类型会被Java虚拟机的jsr、ret和jsr_w指令。所使用参returnAddress类型的值指向一条虚拟机指令的操作码。与前面介
绍的那些数值类的原生类型不同,returnAddress类型在Java语言之中并不存在相应的
类型,而且也无法在程序运行期间更改。

3.4 boolean类型

虽然Java虚拟机定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替
Java虚拟机直接支持boolean类型的数组。
在Oracle公司的虚拟机实现里,Java语言中的boolean数组将会被编码成Java虚拟机
的byte数组,每个boolean元素占8位。
Java虚拟机会把boolean数组元素中的true值采用1来表示,false值采用0来表
示,当Java编译器把Java语言中的boolean类型值映射为Java虚拟机的int类型值时,
也必须采用上述表示方式。

2.4 引用类型与值

Java虚拟机中有三种引用类型:类类型(class type)、数组类型(array type)和接口类型( interface type)。这些引用类型的值分别指向动态创建的类实例、数组实例和实现了某个接口的类实例或数组实例。
在引用类型的值中还有一个特殊的值:null,当一个引用不指向任何对象的时候,它的值就用null来表示。一个为null的引用,起初并不具备任何实际的运行期类型,但是
它可转型为任意的引用类型。引用类型的默认值就是null。
Java虚拟机规范并没有规定null在虚拟机实现中应当怎样用编码来表示。

5运行时数据区

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

5.1 pc寄存器

Java虚拟机可以支持多条线程同时执行,每一条Java虚拟机线程都有自己的pc(program counter)寄存器
在任意时刻,一条Java虚拟机线程只会执行一个方法的代码,这个正在被线程执行的方法称为该线程的当前方法(current method)。如果这个方法不是native的,那pc寄存器就保存Java虚拟机正在执行的字节码指令的地址,
如果该方法是native的,那pc寄存器的值是undefined。

5.2 Java虚拟机栈

每一条Java虚拟机线程都有自己私有的Java虚拟机栈(Java Virtual Machine stack),这个栈与线程同时创建,用于存储栈帧(Frame)
Java虚拟机栈用于存储局部变量与一些尚未算好的结果。另外,它在方法调用和返回中也扮演了很重要的角色。因为除了栈帧的出栈和入栈之外,Java虚拟机栈不会再受其他因素的影响,所以栈帧可以在堆(应该是java虚拟机栈)中分配,Java虚拟机栈所使用的内存不需要保证
是连续的。

Java虚拟机规范既允许Java虚拟机栈被实现成固定大小,也允许据计算动态来扩展和收缩。如果采用固定大小的Java虚拟机栈,那每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。
可能的异常:
StackOverflowError异常。
个OutOfMemoryError异常。

5.3 Java堆

在Java虚拟机中,堆(heap)是可供各个线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。
Java堆在虚拟机启动的时候就被创建,它存储了gc垃圾收集器)所管理的各种对象,
受管理的对象无需也无法显式地销毁。
java堆的容量可以是固定的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。Java堆所使用的内存不需要保证是连续的。
可能异常:
OutOfMemoryError异常。

5.4方法区

在Java虚拟机中,方法区(methodarea)是可供各个线程共享的运行时内存区域
它存储了每一个类的结构信息,例如,
**运行时常量池( runtime constant pool)、
字段和方法数据、
构造函数和普通方法的字节码内容,
还包括一些
在类、实例、接口初始化时用到的特殊方法)**。

方法区在虚拟机启动的时候创建,虽然方法区是堆的逻辑组成部分,但是简单的虚拟机实现可以选挥在这个区域不实现垃圾收集与压缩。方法区在实际内存空间中可以是不连续的。
方法区可能发生如下异常情况:
OutOfMemoryError异常。

5.5运行时常量池

运行时常量池( runtime constantpool)是class文件中每一个类或接口的常量池表(constant_pool table)的运行时表示形式
它包括了若干种不同的常量。
每一个运行时常量池都在Java虚拟机的方法区中分配,在加载粪和接口到虚拟机后,就创建对应的运行时常量池
可能异常情况:
个OutOfMemoryError异常。

5.6本地方法栈

Java虚拟机实现可能会使用到传统的栈(通常称为Cstack)来支持native方法(指使用Java以外的其他语言编写的方法)的执行,这个栈就是本地方法栈(native method stack)。
可能异常情况:
StackOverflowError异常,OutOfMemoryError异常。

6栈帧

栈帧(frame)是用来存储数据和部分过程结果,用于支持虚拟机进行方法调用和方法执行的数据结构,同时也用来处理动态链接
( dynamic linking)、方法返回值和异常分派(dispatch exception)。
栈帧随着方法调用而创建,随着方法结束而销毁
栈帧的存储空间由创建它的线程分配在Java虚拟机栈之中,每一个栈帧都有自己的本地变量表、操作数栈和指向当前方法所属的类的运行时常量池的引用。 第一个方法从调用开始到执行完成,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

本地变量表和操作数栈的容量在编译期确定,并通过相关方法的code属性保存及提供给栈帧使用。因此,栈帧数据结构的大小仅仅取决于Java虚拟机的实现。
对局部变量表和操作数栈的各种操作,通常都指的是对当前栈帧的局部变量表和操作数栈所进行的操作
栈帧是线程本地私有的数据,不可能在一个栈帧之中引用另外一个线程的栈帧

6.1 局部变量表

每个栈帧内部都包含一组称为局部变量表的变量列表
编译期存储于类或接口的二进制表示之中,即通过方法的code属性保存及提供给栈帧使用。
一个局部变量可以保存一个类型为boolean、byte、char,short、int、float、reference或returnAddress的数据
两个局部变量可以保存一个类型为long或double的数据

6.2操作数栈

每个栈帧内部都包含一个称为操作数栈的后进先出(Last-In-First-Out,LIFO)栈。
栈帧中操作数栈的最大深度由编译期决定,并且通过方法的code属性保存及提供给栈帧使用。
栈帧在刚刚创建时,操作数栈是空的。
Java虚拟机提供一些字节码指令来从局部变量表或者对象实例的字段中复制常量或变量值到操作数栈中,也提供了一些指令用于从操作数栈
取走数据、操作数据以及把操作结果重新人栈。 在调用方法时,操作数栈也用来准备调用方法的参数以及接收方法返回结果。
例如,iadd字节码指令的作用是将两个int类型的数值相加,
它要求在执行之前操作数栈的栈顶已经存在两个由前面的其他指令所放人的int类型数值。
在执行iadd指令时,两个int类型数值从操作栈中出栈,相加求和,然后将求和结果重新入栈。在操作数栈中,一项运算常由多个子运算( subcomputation)嵌套进行,一个子运算过程的结果可以被其他外围运算所使用。
操作数栈的每个位置上可以保存一个Java虚拟机中定义的任意数据类型的值,包括long和double类型。

在任意时刻,操作数栈都会有一个确定的栈深度,一个long或者double类型的数据
会占用两个单位的栈深度,其他数据类型则会占用一个单位的栈深度。

6.3动态链接

每个栈帧内部都包含一个指向当前方法所在类型的运行时常量池)的引用,以便对当前方法的代码实现动态链接。
在class文件里面,一个方法若要调用其他方法,或者访问成员变量,则需要通过符号引用( symbolic reference)未表示,动态链
接的作用就是将这些以符号引用所表示的方法转换为对实际方法的直接引用

7 对象的表示

Java应拟机规范不强制规定对象的内部结构应当如何表示。
在Oracle的某些Java虚拟机实现中,指向对象实例的引用是一个指向句柄的指针,
这个句柄叉包含了两个指针,其中一个指针指向一张表格
此表格包含该对象的各个方法,还包含指向Class对象的指针,那个Class对象用来表示该对象的类型
句柄的另外一个指针指向分配在堆中的对象实例数据

JVM8(4)java虚拟机内部结构相关推荐

  1. 《java虚拟机规范SE7》整理——第四章:Class文件格式

    按照<java虚拟机规范SE7>章节顺序整理的笔记. 目录: ClassFile格式(注:也就是class文件的总结构) 描述符和签名 常量池 字段 方法 属性 Java虚拟机代码约束 C ...

  2. 小白都能看得懂的java虚拟机内存模型

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:土豆是我的最爱 blog.csdn.net/qq_37141 ...

  3. java虚拟机及加载class文件的原理机制

    2019独角兽企业重金招聘Python工程师标准>>> (点击获取更多资料的下载) java 虚拟机 ‎2007‎年‎4‎月‎23‎日,‏‎14:18:00 | chenweicai ...

  4. vilatile 深入理解java虚拟机_深入理解Java虚拟机(jvm性能调优+内存模型+虚拟机原理)...

    本套课程从虚拟机的发展历史,虚拟机的内存结构,对象的分配与回收以及字节码,类加载等多个方面深入地对Java虚拟机进行了剖析.内容详实,语言通俗易懂.理论结合实践,让学习本套视频的朋友可以更快的理解虚拟 ...

  5. linux修改java内存大小_Linux 和 windows修改java虚拟机内存大小

    1.Java内存区域划分: 运行时的数据区:方法区和堆(各个线程共享的内存区域),程序计数器.Java虚拟机栈和本地方法栈(线程私有的) 程序计数器:当前线程所执行字节码的行号指示器,字节码解释器就是 ...

  6. java虚拟机参数优化_JAVA虚拟机JVM参数优化(2):垃圾收集算法选择

    JAVA虚拟机JVM优化重要性,昨天JAVA虚拟机JVM参数优化(1)文章中已经描述,今天我们来讨论JAVA虚拟机在不同性能要求下如何选择三种垃圾收集算法. JVM内部结构如下图所示: 串行收集用于单 ...

  7. java虚拟机规范 51cto_java虚拟机

    最近学习java虚拟机做了一些整理,会陆续发完. Java虚拟机 一.概念:当我们谈到java虚拟机的时候,有可能指下面3个方面: 1):抽象java虚拟机的规范. 2):一个java虚拟机具体的实现 ...

  8. Java虚拟机(九)——方法区

    文章目录 堆.栈.方法区的交互关系 线程是否共享: 三者的交互关系: 方法区的理解 方法区的位置 基本理解: 设置方法区大小 JDK7以前 JDK8及以后: 方法区的内部结构 方法区存储什么 类型信息 ...

  9. Java虚拟机(六)——虚拟机栈

    文章目录 虚拟机栈 虚拟机栈概述 出现背景: 优点 缺点 内存中的栈和堆 基本内容 Java虚拟机栈是什么 生命周期 作用 栈的优点 常见的错误有哪些 栈的存储单位 栈的运行原理 栈帧的内部结构 局部 ...

最新文章

  1. TensorFlow 资源汇集
  2. Spark读取文本文件并转换为DataFrame
  3. CRM WebUI and Hybris的Product页面标题实现
  4. 蓝桥杯2017初赛-k倍区间-前缀和
  5. Net处理html页面元素工具类(HtmlAgilityPack.dll)的使用
  6. [转]Reporting Service部署之访问权限
  7. Web.config中用customErrors可以自定义默认的出错页面
  8. comsol 5.3 matlab,COMSOL5.3在Linux下的安装
  9. 身为一个程序员该怎么去判断一个工作的好坏?
  10. gold storm翔_牙狼GOLD STORM翔的人物简介
  11. C# 同间字查询 (汉字转拼音 拼音转汉字 简体繁体互转 )
  12. zabbix mysql trapper_zabbix的trapper(补获器)使用
  13. ant jeecg vue 前端通过dom节点 导出xlsx表格
  14. Win11新加硬盘不显示的解决方法
  15. iRobot 推出 Create 3,内置 ROS 2 机器人开发平台(转载)
  16. 去哪儿网一面:工厂方法模式
  17. 云计算课程作业专业词汇
  18. 基于需求的用户访谈的访谈提纲(上)
  19. 头肩模拟器在免提或头戴式终端测试中的应用
  20. 从一条sql的执行流程来详细了解Buffer Pool

热门文章

  1. 华为模拟器小型网络组建
  2. 深度学习_深度学习基础知识_TTA(测试时增强)
  3. 记录一下tomcat的./startup.sh完成之后没有tomcat进程问题
  4. 重新运行一次阿里云服务器.从零开始搭建.?log-换-服务器
  5. Linux 下使用 tplink wn823N 无线网卡
  6. 推荐系统4--AutoRec与Deep Crossing(改变神经网络的复杂程度)
  7. iOS系统的各种设备识别码
  8. Sublime Text正确的打开方式
  9. TrackRay:打造一款自己的渗透测试框架
  10. 用计算机答题答案提交后能否改错,湘大职院计算机.VF复习参考题1+详细答案