JVM的一些知识

[复制链接]
发表于 2025-10-12 07:19:58 | 显示全部楼层 |阅读模式
JVM简介

JVM 是 Java Virtual Machine 的简称,意为 Java 假造机。
假造机是指通过软件模仿的具有完备硬件功能的、运行在一个完全隔离的情况中的完备盘算机体系。常见的假造机:JVM、VMwave、Virtual Box。
JVM 和其他两个假造机的区别:

  • VMwave与VirtualBox是通过软件模仿物理CPU的指令集,物理体系中会有许多的寄存器;
  • JVM则是通过软件模仿Java字节码的指令集,JVM中只是重要生存了PC寄存器,其他的寄存器都进
    行了裁剪。
    JVM 是一台被定制过的实际当中不存在的盘算机。
JVM 类加载的过程


  • 加载
    Java步调的 .Java 文件, 通过 javac 编译成 .class 文件, 存储在硬盘上, 当运行 Java 历程的时间, jvm 必要读去 .class 文件内里的内容,
  • 验证
    验证读到的 .class 文件的数据是否精确, 是否合法 (在 Java 的标准文档中, 明确界说了 .class 文件的格式是什么样的)
  • 准备
    根据读取到的内容尾类的静态变量分配内存, 将其设置为初始值好比 boolean 就设置成 false, 对象引用就设置成 null, 不会举行赋值的操纵
    (创造一个内存空间, 全部设为初始值)
  • 剖析
    Java假造机将常量池内的符号引用更换成了直接引用  (符号引用相当于就是一个名字, 好比 String s = “hello” 符号引用雷同 hello, 直接引用可以明确成内存地点好比 0x19)
  • 初始化
    针对类对象做末了的初始化操纵, 实行静态成员的赋值语句 (此时静态代码块以及父类也会在这一阶段被加载)
殒命对象的判断算法

1. 引用计数法

给对象增长一个计数器, 每当有一个地方引用这个对象, 计数器就 +1, 当引用失效的时间就 -1, 一旦对象的计数器变成了 0, 就代表失效
但是主流的 jvm 都没有利用引用计数法, 重要是无法办理循环引用的标题
  1. public class Test {
  2. public Object instance = null;
  3. private static int _1MB = 1024 * 1024;
  4. private byte[] bigSize = new byte[2 * _1MB];
  5. public static void testGC() { Test test1 = new Test(); Test test2 = new Test(); test1.instance = test2; test2.instance = test1; test1 = null;
  6. test2 = null;
  7. // 强制jvm进行垃圾回收
  8. System.gc(); }
  9. public static void main(String[] args) {
  10. testGC(); }
  11. }  
复制代码
好比以上的情况, 就会发生无法接纳的情况, 但是着实也引入了回路检测的算法, 可以办理这种标题
2. 可达性分析算法


通过一系列成为 GC Root 的对象, 举行不停向下搜索
(雷同 jvm 手上有一份名单, 然后全部的 root 举行向下搜索, 假如发现有无法到达的对象, 即可分析该对象是不可用的)
GC Root 有许多个好比

  • 栈上的局部变量
  • 元数据区的静态变量
  • 常量池引用指向的对象
垃圾接纳算法

1. 标志扫除算法

先标志再扫除, 根据上述可达性算法, 先从全部的 GC Root 遍历一遍, 标志为存活对象, 之后遍历扫除没有被标志的对象, 从而接纳内存
长处

  • 实现简朴
  • 无需移动对象
缺点
扫除后会产生内存碎片, 导致内存的利用率变低
2. 复制算法

内存地区直接分别成两块, 只利用此中一块, 单举行垃圾接纳的时间, 将存活对象从当前地区, 直接移动到另一块地区, 对当前地区举行团体接纳操纵
长处
空间碎片镌汰
缺点

  • 空间利用率较低
  • 对象多的时间, 复制本钱大
3. 标志整理算法

一样通过 GC Root 对全部对象举行可达性的判断, 标志一下对象是否存活, 对存活的对象举行整理, 一连分列, 整理出一连的空间
长处
办理了内存碎片的标题
缺点
移动整理对象会产生搬运的开销
4. 分代接纳算法


剖析


  • 分成三个区, 分别是伊甸区、幸存区、老年区
  • 开始 new 出来的对象, 都会先放在伊甸区 (伊甸区是比力大的) , 根据履历规律 90% 的对象都是活不外第一轮 GC, 以是剩下活下来的会放到此中一个幸存区, 然后清空另一个幸存者区和伊甸区, 下一轮对象加入伊甸区再次 GC 后, 将幸存的对象和存放上一轮 GC 的存活对象放入到另一个幸存者区, 然后接纳伊甸区和另一个幸存区的空间
  • 当履历过好几轮的 GC 之后, 就会把多轮存活的对象转移到老年代
  • 老年代的 GC 频率相较伊甸区的 GC 频率要低许多
长处

  • 进步了接纳的服从
  • 镌汰了 STW 的时间
缺点
堆内存举行分区管理, 较为复杂
双亲委派模子

输入: 类的全限定名 , 雷同于 java.lang.String

目标

防止用户写的类, 把标准库的类给覆盖掉, 包管标准库的类优先级最高, 扩展库其次, 第三方库的优先级最低
JVM内存地区的分别

1. 步调计数器, 生存了下一条要实行的指令的地点 (下一条指令是 Java的字节码)
2. 堆, jvm 最大的空间, new 出来的对象都在堆上
3.
1. Java 假造机栈, 运行 Java 代码的方法调用关系, 存储函数中的局部变量, 函数的形参, 函数之间的调用关系
2. 当地方法栈, jvm 中 c++ 代码的函数调用关系
4. 元数据区(方法区), 代码中涉及到的类信息, 以及类的 static 属性, 静态变量

堆(线程共享)

堆是全部线程共享的, 分为新生代和老生代, 在堆上的 GC 操纵在上述的分代算法有先容
方法区(元数据区) (线程共享)

用来存储被假造机加载的类信息、静态变量等数据
Java假造机栈(线程私有的)

每个方法在实行的时间都会创建栈帧存储局部变量, 方法出口等等, 常说的堆内存, 栈内存指的就是假造机栈


  • 局部变量表:  存储方法参数和局部变量
  • 操纵栈: 每个方法会天生一个先辈后出的操纵栈
  • 动态链接: 指向常量池的方法引用
  • 方法返回地点: PC 寄存器的地点
当地方法栈(线程私有)

当地方法栈和假造机栈雷同, 但是 Java 假造机栈是给 jvm 利用的, 当地方法栈是给当地方法利用的
步调计数器(线程私有)

用来纪录当火线程实行的行号
当火线程假如实行的是一个 Java 的方法, 这个计数器纪录的是正在实行的假造机字节码指令的地点; 假如实行的是一个 Native 方法, 计数器的值为空 (由于调用的是其他语言的代码, 计数器并没故意义)
!!! 计数器是唯逐一个在 jvm 规范中没有规定任何 OOM 情况的地区 (也就是内存溢出)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表