jvm相关知识

267 阅读7分钟

这是我参与更文挑战的第2天,活动详情查看:更文挑战

一、jdk发展历史

  • 1990 - sun公司 java
  • 1996 - sun公司 JDK1.0
  • 1998 - j2ee j2se j2me
  • 2000 - java hotspot virtual machine 成为默认java 虚拟机
  • 2003 - Scala、Groovy 加入java平台
  • 2005 - JDK 1.5 -> 5.0
  • 2006 - JDK 6.0 java 开源并建立了OpenJDK;Hotspot 成为 OpenJDK 默认的虚拟机
  • 2008 - Oracle收购BEA 得到 JRockit 虚拟机
  • 2010 - Oracle收购sun 获得java商标及Hotspot虚拟机;Oracle拥有 Hotspot、- JRockit两款虚拟机,计划后期整合为: HotRockit (2014年其实已经整合)
  • 2011 - jdk7发布 -->>垃圾回收器 G1 --->>
  • 2014 - jdk8 -->>
  • 2017 - jdk9发布 将G1设置为默认GC 替代CMS
  • 2018 - jdk11发布 --->>垃圾回收器 ZGC --->>
  • 2019-03 - jdk12发布
  • 2019-09 - jdk13发布
  • 2020-03 - jdk14发布
  • 2020-09 - jdk15发布

二、jvm相关

1.jvm生命周期

2.常见虚拟机

  • SUN Classic VM
  • Exact VM
  • Hotspot VM:其他两个商用虚拟机没有 方法区的概念
  • BEA JRockit VM 商用 专注于服务器端;不包含解析器的实现;最快的JVM
  • IBM J9 VM (IT4J) 商用

三、类加载子系统(重点)

1.类加载过程

  • 类加载子系统
  1. 负责从文件系统或网络中加载class文件 class文件在文件开头有特定 的 文件标识 (A... Hexadecimal CA FE BA BE)
  2. ClassLoader 只负责class文件的加载,至于是否可以运行、则由Execution Engine决定
  3. 加载的类信息存放于一块 称为 方法区 的内存空间、(物理磁盘->内存 形成内存实例)
  • 类加载的7个步骤 加载、链接(验证、准备、解析)、初始化、使用、卸载
  1. 加载(loading)

  2. 链接(Link)

    • 验证(Verify)
    • 准备(Prepare)
    • 解析(Reslove)
  3. 初始化(initial)

  4. 使用

  5. 卸载

2.双亲委派机制

  • java虚拟机对 class文件 采用的是 【按需加载】 的方式;
  • 在加载某个类的时候, java虚拟机 采用的是 【双亲委派机制】
    • 按需加载】:需要使用该类时候 才会去将class文件加载到内存 生成class对象
    • 双亲委派机制】:把请求交给父类处理、它是一种任务委派模式
  • 优点
    1. 避免类的重复加载
    2. 保护程序安全、防止核心API轻易被篡改 - 沙箱安全机制

3. jvm整体结构

0.png

四、运行时数据区(重点)

1.程序计数器

  • 程序计数器(Program Counter Register
    • PC寄存器 -- 程序钩子
    • 作用:用来存储下一条指令的地址(存储的是当前栈帧对应的地址)
    • 任何时间一个线程都有一个方法在执行,也就是所谓的【当前方法】
    • 程序计数器会存储【当前线程】 正在执行的 java方法的jvm地址;如果是native方法,则值为undefined
    • 此区域不会出现OutOfMemory
面试问题:
       使用PC寄存器存储字节码指令地址用什么用呢?
       为什么使用PC寄存器存储当前线程地址?
回答:
       程序运行过程中,cpu不停切换线程,这时候切换回来的时候就需要知道从哪个地方开始继续执行。
       [执行引擎中 JVM字节码解释器] 需要通过改变PC寄存器的值来明确下一条应该执行什么样的字节码指令。

2.栈-虚拟机栈

  • 栈-虚拟机栈(VM stack
    • 局部变量表 (LV) Local Variable
      • 定义为一个‘数字数组’
      • 主要存储:方法参数、定义方法内部的局部变量(包括基本数据类型、对象引用、以及returnAddress类型)
      • 局部变量表 所需容量的大小 是在编译时期确定下来的
      • slot(变量槽): 局部变量表 最基本的存储单元 (32位以内 占用 1个槽;64位类型 占用 2个)
    • 操作数栈 (OS) Operand Stack
      • 在方法执行过程中,根据字节码指令,往栈中写入数据或者提取数据;(即:入栈push 出栈 pop操作
      • 也是一个数组结构;操作数栈 所需容量的大小 是在编译时期确定下来的 与 局变量表 大小是两回事
      • 栈顶缓存技术:将栈顶的元素 全部缓存在物理CPU寄存器中、以此降低对内存的读写次数、提升执行引擎的执行效率
    • 动态链接 (DL) (帧数据区)
      • 也叫:'指向运行时常量池的方法引用'
      • 每个栈帧内部都包含一个指向 运行时常量池 中该栈帧所属方法的引用、
      • 每个栈帧内部都包含 一个 动态链接
    • 方法返回地址 (RA) (帧数据区)
      • 作用:【用来存储 该方法(当前方法)的pc寄存器的值】
      • 本质上:方法的退出就是当前栈帧出栈的过程。此时,需要恢复上层方法的局部变量表、操作数栈、将返回值压入调用者栈帧的操作数栈、设置pc寄存器值,让调用者方法继续执行下去。
    • 一些附加信息 (帧数据区)
      • 栈帧中还允许携带与java虚拟实现相关的一些附加信息。
      • 例如:对程序调试提供支持的信息
** 数据存放:
      栈空间存放的数据:
         方法内部基本类型数据、方法内部引用类型地址
      堆空间存放的数据:
         对象信息、类成员属性等
** -Xss 设置 虚拟机栈大小空间 
** 栈帧
      - 栈中 以 栈帧(stack frame) 格式存在
      - 方法与栈帧  完全 一对一 的关系
      - 栈帧 是一个内存区块,是一个数据集,维系着方法执行过程中各种数据信息

3.栈-本地方法栈

  • 栈-本地方法栈(Native Method stack
    • 本地方法:native 关键字修饰的方法叫本地方法,方法的实现为非java语言,(非抽象法,与abstract关键字不能同时使用)
    • Native Method : java调用非java代码的接口
    • java 虚拟机栈用于管理java 方法的调用
    • 本地方发栈 用于管理 本地方法的调用

4.堆

  • 堆(heap
    • 几乎所有的对象实例及数组 都应当在运行时分配在堆上
    • 两个关键参数
    • 年轻代
    • 老年代
    1个进程 -> 
          1个jvm实例 -> 
                1 运行时数据区 -> 
                      1个 方法区  | 1个堆   
                      N个 程序计数器 | N个虚拟机栈 | N个本地方法栈

    概念:
           一个jvm实例只存在一个堆内存;
            堆在 虚拟机启动时候被创建,堆的大小随之被确定,
            堆是jvm管理 中最大的一块内存区间

            jvm规范规定: 堆空间 -> "物理上不连续  逻辑上连续"

5.方法区/元空间

  • 方法区/元空间(Method area/metaspace
    • 存放的内容
      • 类(类型)信息
      • 方法信息
      • 运行时常量池
      • 静态变量
      • JIT代码缓存
      • 域信息(属性信息)
    • 参数
JDK1.7 :
        -XX:PermSize=100M	      永久代初始分配空间
        -XX:MaxPerSize=100M	      永久代最大可分配空间
JDK1.8:
        -XX:MetaspaceSize=100M	      元空间初始分配空间
        -XX:MaxMetaspaceSize=100M     元空间最大可分配空间

命令行查看参数:
        jinfo -flag MetaspaceSize
        jinfo -flag MaxMetaspaceSize

五、执行引擎

  • 解释器
    • 功能:逐行见识字节码
    • 优点:速度快
  • 编译器 JIT(just in time)
    • 功能:寻找热点代码 进行JIT编译 将这部分缓存起来
- [作用]:字节码指令转换为机器指令
- 主要面对 --> [java 操作数栈]
- 执行一行一行的字节码指令  -- 转换为 --> 机器指令

六、垃圾回收

  • 【垃圾】 概念:
  • 【内存泄漏】 概念:
  • 垃圾标记阶段
    • 引用计数算法(reference count)
    • 可达性分析算法
  • 垃圾清除阶段
    • 标记-清除算法
    • 复制算法
    • 标记-压缩算法
    • 分代收集算法

参考资料: