先来一张运行时数据区的图

概览

运行时数据区的内容的生命周期是不同的
有的是随着虚拟机的开始结束
有的是随着每个线程的开始结束而开始结束

线程独有:
PC寄存器(程序计数器)
虚拟机栈
本地方法栈线程共享:
堆
方法区

一个程序每有一个线程 就有一组PC寄存器 虚拟机栈 本地方法栈
他们共用一个堆、方法区
正因为堆和方法区是共用的 所以可能会发生线程安全问题等
而我们所谓的JVM调优 几乎都是在堆上的优化
因为几乎95%的垃圾回收都在堆 我们优化的主要也是这方面


PC寄存器

PC寄存器相对于其他组件来说 是一个最轻量 最简单的内容 他是每个线程独有的 负责记录线程执行的指针位置
之后由字节码解释器来PC寄存器中知道此线程执行到了哪里 同时因为特别特别轻量 所以PC寄存器是唯一一块没有没有规范任何oom的区域
CPU在切换时间片的过程中 执行引擎需要准确的知道自己需要执行哪条指令

举个例子 线程A和线程B同时执行 线程A执行到第20行 失去了时间片 此时PC寄存器存储第21行的地址信息
等到线程A再次获得时间片的时候 字节码解释器就可以直接在PC寄存器中继续执行程序 也是因为每个线程的执行程度不同
所以最好的方法就是每个线程独立拥有自己的PC寄存器


虚拟机栈

以前刚学java的时候 刻板的以为内存只有两部分 栈和堆 大概就是栈管运行 堆管存储 不过其实真正的内存模型比这个复杂得多
之前理解的这个栈 就是虚拟机栈了 虚拟机栈也是线程独有的 每个线程创建的时候都有同时创建一个虚拟机栈 这个栈中保存着一个一个
栈帧,对应着一个一个的java方法 也就是你有多少个方法 就有多少个栈帧

定义两个方法 用一个线程去执行 因为只有一个线程 所以会创建一个虚拟机栈
一次次的方法调用 就对应的一次次的栈帧入栈出栈

作用就是保证java程序的运行 保存方法的局部变量(八种基本数据类型和引用对象的地址) 部分结果 并参与方法的调用和返回

虚拟机栈是一种有效的分配存储方式 访问速度仅次于PC寄存器 JVM对虚拟机栈的操作只有两个 —>每个方法执行 伴随着方法入栈
—> 方法执行结束时 方法出栈 对于栈来说不存在垃圾回收问题 —>不存在GC
但是存在OOM 随便写个递归就栈溢出了-。-

虚拟机栈的异常内容

java虚拟机允许java栈的大小是固定值或者是动态

  • 如果是固定值 当请求分配的栈容量超过了允许最大容量的时候 就会抛出StackOverFlowError
  • 如果是动态变化的 在尝试扩展的时候无法申请到足够的内存 或者在创建新线程的时候没有足够的内存去创建对应的虚拟机栈 就会抛出OutOfMemoryError

调优

可以通过 -Xss [size] 来设置栈大小

栈中到底存储着什么

  • 每个线程都有自己的虚拟机栈 栈中的数据都是以栈帧的格式存在
  • 这个线程上正在执行的所有方法都各自对应一个栈帧 (方法和栈帧是一一对应的) 一个方法执行 栈帧就入栈 方法结束 栈帧就出栈
  • 栈帧是一个内存区块 是一个数据集 维系着方法执行过程中的各种数据信息
  • 一条活动的线程中 一个时间点上只会有一个活动的栈帧 ,只有栈顶栈帧(当前栈帧)就是当前执行的方法是有效的, 这个方法就是当前方法,定义这个方法的就是当前类
  • 执行引擎运行的所有字节码指令只针对当前栈帧进行操作
  • 不同栈帧不允许互相引用 即不可能在一个栈帧中引用另一个线程的栈帧
  • java方法有两种返回函数的方式 一种是正常的函数返回 另一种是抛出异常 不管哪种方式 当前栈帧都将被弹出 —> 当某个栈帧抛出异常的时候 如果没有处理 会向上抛 当前栈帧弹出 然后下一个当前栈帧如果没捕获异常 那么继续


一个栈帧可以由五部分组成

  • 局部变量表
  • 操作数栈
  • 方法返回地址
  • 动态链接
  • 一些附加信息

局部变量表

局部变量表定义为一个数字数组,主要用于储存方法参数和定义在方法体内的局部变量,
这些数据包括基本数据类型和引用类型 还有返回值地址
局部变量表中没有线程安全性问题
局部变量表的大小是在编译期间就确定下来的 在运行期间不会更改局部变量表的大小
用javap -v XXX.class 之后 可以在方法中的Code里面的Maximum local variables看到大小

方法嵌套的调用次数由栈的大小决定,一般来说,栈越大,方法嵌套调用次数越多。
局部变量表中的变量 只在当前方法中有效 虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程。当方法调用结束之后 随着方法栈帧的销毁 局部变量表也会随之销毁

局部变量表中的slot
  • 局部变量表最基本的存储单元是Slot
  • 32位以内的类型只占用一个Slot (包括returnAddress) ,64位的类型占用两个Slot
    —> Byte short char 在存储前被转换成int boolean也被转换成int 0表示false 非0表示true
    —>long 和double 占两个Slot
  • 如果是非静态方法或者是构造方法 Slot槽的第一个(也就是第0个位置) this是第一个
  • 引用类型占一个Slot

补充

  • 在栈帧中 与性能调优关系最为密切的部分就是前面提到的局部变量表
    在方法执行时 虚拟机使用局部变量表完成方法的传递
  • 局部变量表也是重要的垃圾回收根节点 只要被局部变量表中直接或间接引用的对象都不会被回收

操作数栈

  • 操作数栈在方法执行的过程当中 根据字节码指令往栈中写入数据或提取数据 即入栈/出栈
    —>有些字节码指令是讲值压入操作数栈 其余的字节码指令是将操作数取出栈 使用之后再把结果压入栈
    ---->比如 复制 交换 求和等

  • 操作数栈主要用于保存计算过程的中间结果 同时作为计算过程中变量临时的存储空间

  • 操作数栈是随着方法调用(也就是随着栈帧被创建出来) 栈帧刚被创建出来的时候 操作数栈也是空的

  • 每一个操作数栈都会拥有一个明确的栈深度 所需的最大深度在编译期就已经确定好了 保存在方法的Code属性中 为max_stack的值

  • 栈中的任何一个元素可以是任何类型的java数据类型 同时 64位占两个栈深度 32位占一个

  • 操作数栈不能使用索引访问 只能用入栈出栈的形式

  • 如果方法有返回值的话 那返回值也会被压入当前栈帧的操作数栈中 并更新PC寄存器中下一条需要执行的指令

  • 其实我们平时说的 栈和堆 这个栈指的就是虚拟机栈中的操作数栈

栈顶缓存技术

HotSpot JVM设计者们提出栈顶缓存技术 将栈顶元素全部缓存在物理CPU的寄存器中
以此降低内存的读写次数 提升执行引擎的效率

动态链接(指向运行时常量池的方法引用)

  • 每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用。
    包含这个引用的目的就是为了支持当前方法能够实现动态链接
  • 在JAVA源文件被编译到字节码文件中 所有的变量和方法引用都作为副号引用 ,
    保存在class文件的常量池里
    比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的
    那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用

方法的调用

  • 静态链接 当一个字节码文件被装载到虚拟机的时候 如果被调用的目标方法在编译器可知
    且运行期间保持不变 ,这种情况 符号引用转化为直接引用的过程称为静态链接
  • 动态链接 如果被调用的方法在编译期间无法被确定下来 在运行期间才能确定下来 这种情况为动态链接

---->举个例子 动态链接(晚期绑定) 在代码中提现为接口或者基类调用方法

方法重写的本质

  1. 找到操作数栈顶的第一个元素所执行的对象实际类型 记做C
  2. 如果在类型C中找到与常量中的描述符合简单名称都相符的方法 进行权限校验
    如果通过 则返回这个方法的直接引用 查找过程结束 如果不通过 则抛出java.lang.IllegalAccessError异常
  3. 否则 按照继承关系从下往上依次对C的各个父类进行第二步的搜索和验证过程。
  4. 如果始终没有找到合适的方法 则抛出 java.lang.AbstractMethodError异常

IllegalAccessError介绍:
程序试图访问或修改一个属性或调用一个方法 这个属性或方法,你没有访问权限 。一般这个类会引起编译器异常 这个错误如果发生在运行时 就说明一个类发生了不兼容的改变

方法返回地址

  • 存放调用该方法的PC寄存器的值
  • 一个方法的结束 有两种情况 正常返回和出现未处理的异常
  • 无论哪种方式退出 调用者的pc计数器的值作为返回地址
正常和异常退出的区别就是   通过异常完成出口退出的不会给他上层的调用者产生任何的返回值

一些附加信息

其实需要知道栈帧中还有这么个东西就行了…


本地方法栈

什么是本地方法?
native method 就是本地方法  该方法的实现由非java语言实现 比如C
  • 本地方法栈也是线程私有的
  • 也允许被实现成固定或者是可动态扩展的大小
  • 当调用本地方法时 它就进入了一个全新的而且不受虚拟机限制的世界 它和虚拟机拥有同样的权限
    —>甚至可以直接使用本地的寄存器和本地内存
  • 在HotSpot中 直接将本地方法栈和虚拟机栈合二为一

[隐匿的学习笔记]JVM(2)运行时数据区相关推荐

  1. JVM初学之JVM的运行时数据区

    什么是JVM的运行时数据区: 看下图: java虚拟机在该虚拟机进程运行过程中定义了各种各样的运行时数据区.用于存储java程序运行时各种不同的数据.有些运行时数据区是在java虚拟机进程开始时就创建 ...

  2. 【JVM】运行时数据区介绍,程序计数器和虚拟机栈详解

    JVM越来越是Java面试中的重头戏,今天来总结一下JVM运行时数据区的相关内容. 文章目录 JVM运行时数据区 JVM运行时数据区内部结构 程序计数器(PC寄存器) 程序计数器的介绍 PC寄存器的实 ...

  3. 浅谈JVM之运行时数据区

    Java内存结构 提到Java执行流程,我们就要关注Java的内存结构.我们还要了解到的一个概念就是Java内存结构≠Java内存模型.今天我们先不深入展开. 如上图所示,首先Java源代码文件(.j ...

  4. 【JVM】运行时数据区概述(程序计数器、虚拟机栈、本地方法栈)

    前言 本节主要讲的是运行时数据区,也就是下图这部分,它是在类加载完成后的阶段 当我们通过前面的:类的加载-> 验证 -> 准备 -> 解析 -> 初始化 这几个阶段完成后,就会 ...

  5. JVM之运行时数据区(方法区)

    文章目录 1. 堆.栈.方法区的交互关系 2. 方法区的理解 3.设置方法区大小与OOM 方法区OOM 4.方法区的内部结构 类型信息 域信息(成员变量) 方法信息 non-final的类变量 运行时 ...

  6. 欧尼酱讲JVM(04)——运行时数据区简介

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

  7. JVM总结-运行时数据区

    文章目录 运行时数据区 一.程序计数器 二.虚拟机栈 1.是什么? 2.生命周期 3. 作用 4.特点 5.可能出现异常 6.设置栈内存大小 7.栈帧 8.栈帧的内部结构 8.1局部变量表 8.2Sl ...

  8. JVM学习笔记:Java运行时数据区域

    JVM执行Java程序的过程中,会使用到各种数据区域,这些区域有各自的用途.创建和销毁时间.根据<Java虚拟机规范>,JVM包括下列几个运行时数据区域,如下图所示: 其中红色部分是线程私 ...

  9. Java 虚拟机学习笔记 | 运行时数据区总结

    前言 要想学习好 Java,Java虚拟(JVM)的学习是绕不开的.学习 Java虚拟(JVM)首先就要先了解的就是Java虚拟(JVM)运行时数据区. 在Java语言和虚拟机规范中对运行时数据区进行 ...

  10. 从头开始学习->JVM(八):运行时数据区(下)

    前言 在上一篇文章中,我们了解到了JVM的运行时数据区,基本被划分了5个区域. 程序计数器(pc寄存器) java虚拟机栈 本地方法栈 java堆 方法区(永久代,元空间). 而上一篇文章中,我们详细 ...

最新文章

  1. C#获取文件夹下的所有文件的方法
  2. 用户请求接口信息日志记录
  3. 《Effective C#》Part I:第一部分总结
  4. Python 多种算法模型对比
  5. java集合——树集(TreeSet)+对象的比较
  6. mysql以秒为单位限制资源_MYSQL中限制资源的使用
  7. Redis:14---常用功能之(Pipeline)
  8. 软件设计师 - UML图
  9. Springmvc源码分析、底层原理
  10. 详解Python中的序列解包(2)
  11. 将print的内容保存到txt文本中
  12. listView 下拉动态加载数据
  13. 【干货】Vray渲染器的使用方法
  14. 网络疯传华为面试题:800公斤牛,过承重700公斤的桥,有答案了?
  15. 【Scikit-Learn 中文文档】处理文本数据 - scikit-learn 教程 | ApacheCN
  16. 深度学习实战14(进阶版)-手写文字OCR识别,手写笔记也可以识别了
  17. layui登陆验证页面模板(滑块学习)
  18. Visual Studio 许可证已过期
  19. 微信公众平台推出微信保护提升微信账号安全 附微信保护开启教程
  20. 【岩熹攻略】议息大会后,国庆主题迎布局良机!

热门文章

  1. cd linux给u盘安装程序,CDLINUX U盘安装教程
  2. WinRAR下载官方免费版
  3. mapbox/minemap 获取比例尺
  4. 浏览器警告:provisional headers are shown
  5. 浅析Tone mapping
  6. 总结:硬盘随机读写与顺序读写的性能差异
  7. DT|一文看完企业绩效管理系统产品(EPM)的前世今生
  8. 专业词汇扫盲:MRR(Mean reciprocal rank) ,long-tail,link prediction
  9. windows注册表操作——备份,还原注册表,清除注册表卸载残留信息
  10. psd 解析 java_PSD解析工具实现(一)