一、前言

  为什么要学习了解Java虚拟机

  1.我们需要更加清楚的了解Java底层是如何运作的,有利于我们更深刻的学习好Java。

  2.对我们调试错误提供很宝贵的经验。

  3.这是合格的Java程序必须要了解的内容。

  基于此,笔者打算出一个Java虚拟机的系列,加深自己对知识点的理解,同时也方便各位有需要的园友。

二、Java虚拟机的定义

  Java虚拟机(Java Virtual Machine),简称JVM。当我们说起Java虚拟机时,可能指的是如下三种不同的东西:

    1.抽象规范。

    2.一个具体的实现。

    3.一个运行中的虚拟机实例。

  Java虚拟机抽象规范仅仅是一个概念,在《The Java Virtual Machine Specification》中有详细的描述。该规范的实现,可能来自多个提供商,并存在于多个平台上,它或者是全部由软件实现,或者是以硬件和软件相结合的方式来实现。当运行一个Java程序的时候,也就在运行一个Java虚拟机实例。注意,我们所说的Java平台无关性是指class文件的平台无关性,JVM是和平台相关的,不同操作系统对应不同的JVM。

三、Java虚拟机的总体框架图

  下图是整个Java虚拟机的总体框架图,之后我们会经常涉及到。

四、Java虚拟机的体系结构

  下图表示了Java虚拟机的结构框图,主要描述了JVM子系统和内存区。

五、Java虚拟机各组成部分

  5.1 类装载子系统

  类装载子系统负责查找并装载类型,Java虚拟机由两种类装载器:启动类装载器(Java虚拟机实现的一部分)和用户自定义类装载器(Java程序的一部分)。类装载子系统负责定位和导入二进制class文件,并且保证导入类的正确性,为类变量分配并初始化内存,以及帮助解析符号引用。类装载器必须严格按照如下顺序进行类的装载。

  1) 装载 -- 查找并装载类型的二进制数据

  2) 连接 -- 执行验证,准备,以及解析(可选),连接分为如下三个步骤

    验证 -- 确保被导入类型的正确性

    准备 -- 为类变量分配内存,并将其初始化为默认值

    解析 -- 把类型中的符号引用转换为直接引用

  3) 初始化 -- 把类变量初始化为正确初始值

  启动类装载器 -- Java虚拟机必须有一个启动类装载器,用于装载受信任的类,如Java API的class文件。

  用户自定义类装载器 -- 继承自ClassLoader类,ClassLoader的如下四个方法,是通往Java虚拟机的通道。

    1. protected final Class defineClass(String name, byte data[], int offset, int length);

    2. protected final Class defineClass(String name, byte data[], int offset, int length, ProtectionDomain protectionDomain);

    3. protected final Class findSystemClass(String name);

    4. protected final void resolveClass(Class c);

  这四个方法涉及到了装载和连接两个阶段,defineClass方法data参数为二进制Java Class文件格式,表示一个新的可用类型,之后把这个类型导入到方法区中。findSystemClass的参数为全限定名,通过类装载器进行装载。resolveClass参数为Class实例,完成连接初始化操作。

  5.2 方法区

  方法区是线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError。

  类信息包括1.类型全限定名。2.类型的直接超类的全限定名(除非这个类型是java.lang.Object,它没有超类)。3.类型是类类型还是接口类型。4.类型的访问修饰符(public、abstract、final的某个子集)。5.任何直接超接口的全限定名的有序列表。6.类型的常量池。7.字段信息。8.方法信息。9.除了常量以外的所有类(静态)变量。10.一个到类ClassLoader的引用。11.一个到Class类的引用。

  着重介绍常量池 -- 虚拟机必须要为每个被装载的类型维护一个常量池。常量池就是该类型所用常量的一个有序集合,包括直接常量和对其他类型、字段和方法的符号引用。它在Java程序的动态连接中起着核心作用。

  5.3 堆

  一个虚拟机实例只对应一个堆空间,堆是线程共享的。堆空间是存放对象实例的地方,几乎所有对象实例都在这里分配。堆也是垃圾收集器管理的主要区域。堆可以处于物理上不连续的内存空间中,只要逻辑上相连就行,当堆中没有足够的内存进行对象实例分配时,并且堆也无法扩展时,会抛出OutOfMemoryError异常。

  5.4 程序计数器

  每个线程拥有自己的程序计数器,线程之间的程序计数器互不影响。PC寄存器的内容总是下一条将被执行指令的"地址",这里的"地址"可以是一个本地指针,也可以是在方法字节码中相对于该方法起始指令的偏移量。如果该线程正在执行一个本地方法,则程序计数器内容为undefined,此区域在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

  5.5 Java栈

  Java栈也是线程私有的,虚拟机只会对栈进行两种操作,以帧为单位的入栈和出栈。每个方法在执行时都会创建一个帧,并入栈,成为当前帧。栈帧由三部分组成:局部变量区、操作数栈、帧数据区。

  局部变量区被组织为一个以字长为单位、从0开始计数的数组。字节码指令通过从0开始的索引来使用其中的数据。类型为int、float、reference和return Address的值在数组中只占据一项,而类型为byte、short和char的值存入时都会转化为int类型,也占一项,而long、double则连续占据两项。

  关于局部变量区给出如下一个例子。

可以看到类方法的首项中没有隐含的this指针,而对象方法则会隐含this指针。并且byte,char,short,boolean类型存入局部变量区的时候都会被转化成int类型值,当被存回堆或者方法区时,才会转化回原来的类型。

  操作数栈被组织成一个以字长为单位的数组,它是通过标准的栈操作-入栈和出栈来进行访问,而不是通过索引访问。入栈和出栈也会存在类型的转化。

  栈数据区存放一些用于支持常量池解析、正常方法返回以及异常派发机制的信息。即将常量池的符号引用转化为直接地址引用、恢复发起调用的方法的帧进行正常返回,发生异常时转交异常表进行处理。

  5.6 本地方法栈

  访问本地方式时使用到的栈,为本地方法服务,本地方法区域也会抛出StackOverflowError和OutOfMemoryError异常。

  5.7 执行引擎

  用户所编写的程序如何表现正确的行为需要执行引擎的支持,执行引擎执行字节码指令,完成程序的功能。后面会详细介绍。

  5.8 本地方法接口

  本地方法接口称为JNI,是为可移植性准备的。

六、总结

  至此,虚拟机的结构就已经大体介绍完了,现在我们只需要有一个初步的了解,后面对各个部分会有更加详细的介绍。谢谢各位观看~

JAVA数组子集_【Java虚拟机】JVM系列学习之JVM体系(一)相关推荐

  1. java 数组 反射_【译】10. Java反射——数组

    ===================================================================================== 用Java反射来处理数组有时 ...

  2. java数组 序列化_程序猿的日常——Java基础之clone、序列化、字符串、数组

    其实Java还有很多其他的基础知识,在日常工作技术撕逼中也是经常被讨论的问题. 深克隆与浅克隆 在Java中创建对象有两种方式: 一种是new操作符,它创建了一个新的对象,并把对应的各个字段初始化成默 ...

  3. java 数组 内存_图解Java数组的内存分配

    1. Java数组是静态的 Java是静态语言,所以Java的数组也是静态的,即:数组被初始化后,长度不可变 静态初始化:显式指定每个数组元素的初始值,系统决定数组长度 String[] books ...

  4. java 数组赋值_自学JAVA每日记录(10)-欢迎指点欢迎共勉

    接上一篇 编程练习:编写一个JAVA程序,创建指定长度的 int 型数组,并生成 100 以内随机数为数组中的每个元素赋值,然后输出数组 要求: 1. 要求通过定义带参带返回值的方法来实现 2. 通过 ...

  5. java数组 初始化_用Java初始化数组

    java数组 初始化 具有使用C或FORTRAN等语言进行编程的经验的人熟悉数组的概念. 它们基本上是一个连续的内存块,每个位置都是某种类型:整数,浮点数或您所拥有的. Java中的情况与此类似,但有 ...

  6. java 数组包含_灵魂拷问:如何检查 Java 数组中是否包含某个值?

    作者 | 沉默王二 责编 | Elle 在逛 programcreek 的时候,我发现了一些专注细节但价值连城的主题.比如说:如何检查Java数组中是否包含某个值 ?像这类灵魂拷问的主题,非常值得深入 ...

  7. java数组搞笑_面试官:小伙子,给我说一下Java 数组吧

    Java 数组 Java 语言中提供的数组是用来存储固定大小的同类型元素. 1.声明数组变量 首先必须声明数组变量,才能在程序中使用数组. dataType[] arrayRefVar; // 首选的 ...

  8. java 数组合并_拼接_详解Java合并数组的两种实现方式

    详解Java合并数组的两种实现方式 发布于 2020-7-27| 复制链接 摘记: 最近在写代码时遇到了需要合并两个数组的需求,突然发现以前没用过,于是研究了一下合并数组的方式,总结如下.1.Syst ...

  9. java hprof 分析_[转]Sun JDK自带JVM内存使用分析工具HProf

    Sun JDK自带JVM内存使用分析工具HProf 2008-10-14 11:27 Sun JDK自带JVM内存使用分析工具HProf       使用Sun JDK自带JVM内存使用分析工具HPr ...

最新文章

  1. Castle IOC容器与Spring.NET配置之比较
  2. 点击图片显示大图(有多张图片可以左右滑动)
  3. flutter 几秒前, 几分钟前, 几小时前, 几天前...
  4. 查看PLC IP 端口_西门子828D数控系统X130接口通讯怪异现象(X130手动设置的 IP)...
  5. 又拍云,音视频CDN加速利器
  6. 现代软件工程—构建之法---第三章:练习与讨论
  7. Bootstarp4 按钮
  8. mac检测是否安装mysql_mac安装mysql
  9. 凹凸性和Jensen不等式
  10. dosbox运行C语言,DosBox的基本设置和安装
  11. Windows下Python的安装与配置
  12. 高性能服务器架构拓扑图,某数据中心架构拓扑图.ppt
  13. oracle建索引时报ora00955 名称已由现有对象使用,“ORA-00955: 名称已由现有对象使用” 这个错误是怎么回事?...
  14. 按照是否执行程序分类
  15. Software Architecture Pattern(Mark Richards)笔记
  16. 怎样在大公司混成中层干部
  17. pip install paddlepaddle 报错 command ‘/usr/bin/gcc‘ failed with exit code 1 或 command ‘gcc‘ 报错
  18. java.lang.NoSuchMethodError: No static method ..........
  19. 三菱FX3U与欧姆龙E5CZ温控器485通讯案例
  20. 校园网测试--ettercap使用

热门文章

  1. 在Linux服务器间数据相互复制
  2. CCNP实验---EIGRP自动汇总
  3. qfiledialog的取消_QFileDialog类(老九学堂C++会员友情翻译,不喜勿喷)
  4. python3档案管理程序源码_php人事档案管理系统,源码免费分享
  5. 搭建Mock Server实践(一)理论篇
  6. 合肥一六八2021高考成绩查询,合肥高考成绩查询入口
  7. 性能测试系列:Jmeter使用记录
  8. MYSQL基本知识:TRUNCATE和DELETE的区别
  9. Python测试转岗网络安全测试,挑战年薪30W+
  10. Fiddler抓取HTTPS最全(强)攻略!