Java知识点总结-JVM篇(持续更新中。。。)

JVM专题

JVM 简介

java virtual machine java虚拟机

问题: JDK JRE JVM 三者之间的关系
问题: JVM模式
Server模式(默认)

​ 针对服务器应用,加载速度慢,运行速度快

Client模式

​ 针对桌面应用,加载速度快,运行速度慢

JVM 体系结构(四个部分)

类加载器-运行时数据区-执行引擎-本地接口

类加载器

概念,作用:将Java代码编译成的.class文件(字节码文件)加载到JVM内存中

分类:
  • BootStrapClassloader 启动类加载器
  • ExtensionClassloader 扩展类加载器
  • ApplicationClassloader 应用类加载器
  • 自定义类加载器
    • 继承ClassLoader类,复写loadClass方法
类装载过程
  • 加载
    • 通过类的权限定名,查找此类的二进制字节码文件,通过该字节码文件创建Class对象
  • 链接
    • 验证
      确保Class文件符合虚拟机规定的CLass文件格式,检查class文件的准确性
    • 准备
      为不含final的类的静态变量分配内存空间并设置初始化值
    • 解析
      将常量池的间接引用转换为直接引用的一个过程
  • 初始化
    • 对静态变量和静态代码块执行初始化工作
  • 使用
    • 程序代码执行时的使用,new出对象程序中的使用
  • 卸载
    • 程序代码退出、异常、结束等,执行垃圾回收
双亲委派机制

​ 当要加载某个类(.class文件)到内存的时候,类加载器不会自己去加载,首先会去询问上一级的类加载器(父加载器)有没有加载这个类,如果父加载器加载了,自己的类加载器就不会加载,否则再去询问上一级加载器有没有加载,直到顶层的启动类加载器都没有加载的时候,此时自己才会去加载。
一句话:即每个儿子都不愿意干活,每次有活就丢给父亲去干,直到父亲说这件事我也干不了时,儿子自己想办法去完成。

运行时数据区
程序计数器

​ 作用:记录程序执行到哪一条指令【通过指针】记录程序执行到的位置
​ 特点:整个JVM虚拟机唯一一个不会产生内存溢出的地方 原因:是有硬件加载的

本地方法栈

​ 作用:执行被native关键字修饰的方法

虚拟机栈

​ 也称作方法栈,主要进行方法调用,方法在栈里面的表现为栈帧(Frames)
​ 特点:线程私有,没有线程安全问题
​ 缺点:会出现栈内存溢出
​ 1、方法进行递归调用过深
​ 2、方法内部操作大对象

​ 堆是Java程序中最大的一块内存区域,用于存储创建的对象实例和数组

  • 堆划分成两个部分
    • 新生代 1/3堆占比
      • Eden 伊甸区
      • Survive 幸存区
        • rom 区 (S0)
          to 区 (S1)
    • 老年代 2/3堆占比
方法区

​ 方法区用于存储类的信息和运行时常量池。
它是一个理论的概念,不同的虚拟机产品实现是不一样的,比如java8所使用的Hotspot虚拟机,它基于元数 据空间(直接内存)实现了方法区。
​ 特点:被各个线程共享,逻辑上属于堆的一个部分、随着虚拟机的创建而创建
​ 缺点:会出现内存溢出

执行引擎-----GC 垃圾回收
如何判断对象是垃圾?
  • 引用计数法

    • 给对象添加一个引用计数器,每当一个地方引用它时计数器加1,引用失效计数器减1,计数器为0说明不引用,就为垃圾

      • 优点 实现简单、判断效率高
      • 缺点 无法解决对象互相循环引用问题

      因为引用计数法无法解决对象互相循环引用问题,所以我们常用的是可达性分析算法

  • 可达性分析算法

    • 当对象到达GC Root没有引用链相连的时候,就证明这个对象是不可用的了,就为垃圾
      • GC Root的种类
        • 虚拟机栈中引用的对象
        • 方法区中的常量引用的对象
        • 方法区中的静态变量引用的对象
        • 本地方法栈中native引用的对象
垃圾收集算法
  • 标记-清除算法
    • 先标记出存活的对象,然后再清除所有未被标记的对象。(通过可达性分析算法来判断存活的对象)
      • 缺点:会产生大量不连续的内存碎片
  • 标记-复制算法(新生代)
    • 先将堆内存一分为二,每次只使用一个区域,然后标记出存活的对象,将被标记的对象复制到另一个区域,再将之前的区域全部清除。
      • 缺点:内存的使用率不高,每次只使用一个内存
  • 标记-整理(压缩)算法(老年代)
    • 先标记所有存活的对象,将所有存活的对象移动到内存的一边,然后清除掉边界以外的其他内存区域
垃圾回收器
  • 新生代
    • Serial
      • 回收算法:标记-复制算法
      • 简单高效的单核机器,Client 模式下默认新生代收集器;
    • Parallel ParNew
      • 回收算法:标记-复制算法
      • GC 线程并行版本,在单 CPU 场景效果不突出。常用于 Client 模式下的 JVM
    • Parallel Scavenge
      • 回收算法:标记-复制算法
      • 目标在于达到可控吞吐量(吞吐量=用户代码运行时间/(用户代码运行时间+垃圾回收时间))
  • 老年代
    • Serial Old
      • 算法:标记-压缩算法
      • 性能一般,单线程版本。1.5 之前与 Parallel Scavenge 配合使用;作为 CMS 的后备预案
    • Parallel Old
      • 算法:标记-压缩算法
      • GC 多线程并行,为了替代 Serial Old 与 Parallel Scavenge 配合使用
    • CMS
      • 算法:标记-清除算法
      • 对 CPU 资源敏感、停顿时间长。标记-清除算法会产生内存碎片,可以通过参数开启碎片的合并整理。 基本已被 G1 取代
  • G1(重点)
    • 特点:将整个Java堆分为多个大小相等的独立区域 ,跟踪各个区域的垃圾堆积的价值大小, 然后在后台维护一个优先队列,每次根据允许的收集时间,优先回收价值最大的区域
    • 判断垃圾算法:可达性分析算法
    • 判断回收算法:标记-整理算法
    • 步骤:
      • 初始标记:G1会标记出GC Roots 直接关联的对象
      • 并发标记:对堆中对象进行可达性分析,找出存活对象,耗时长,与用户进程并发工作
      • 最终标记:修正并发标记期间用户进行继续运行所产生变化的标记
      • 筛选标记:对各个Region 的回收价值排序,然后根据期望的GC停顿时间指定回收计划
    • 场景: 适用于多核大内存机器、GC 多线程并行执行,低停顿、高回收效率;
      • G1垃圾回收器适用于需要处理大堆内存、具有高并发需求、对延迟要求较低以及对分代回收支持的场景。它在这些场景下可以提供更好的性能和更低的停顿时间,帮助优化应用程序的运行效率。
垃圾回收过程
  • 大多数情况下对象在伊甸区分配,当伊甸区没有足够的空间时将发起一次MinorGC 当伊甸区执行MinorGC 后还不足以为对象分配空间时。大对象直接进入老年代,可以用参数设置大对象直接进入老年代,避免频繁MinorGC
  • 如果对象在伊甸区出生,发生MinorGC 后依然存活,且能被Survive(幸存区)容纳,年龄+1 ,达到一定年龄进入老年代,默认是15
  • 占 Survive 区空间一半以上而且年龄相等的对象,大于等于该年龄以上的对象直接进入老年代
  • 发生MinorGC 之前先检查老年代最大可用连续空间是否大于新生代所有对象空间,如果大于说明MinorGC 安全,否则会判断是否允许担保失败,如果允许担保失败,判断老年代最大连续空间是否大于历次晋升到老年代的平均大小 ,如果大于则执行MinorGC 否则FullGC
  • Minor GC
    • 触发条件:
      • 伊甸区 满了
      • 存入对象超过伊甸区剩余空间
  • Major GC
    • 触发条件
      • 老年代空间不足时,会先尝试触发Minor GC。Minor GC之后空间还不足,则会触发Major GC。
  • Full GC
    • 触发条件
      • 显式调用System.gc()方法时法可以请求垃圾回收器执行一次Full GC,可通过-XX:+ DisableExplicitGC 参数来禁止调用System.gc()
      • 当方法区空间不足时
      • 当Minor GC后存活的对象大小超过了老年代剩余空间
      • Minor GC时中Survivor幸存区空间不足时,会判断是否允许担保失败,不允许则触发Full GC。运行则会尝试进行一次Minor GC,并将存活对象直接晋升到老年代中。
      • 如果每次晋升到老年代的对象平均大小>老年代最大可用连续内存空间时,也会触发Full GC
本地接口

本地接口(Native Interface)是一种使Java代码能够调用本地(或原生)方法的机制。本地接口允许Java程序与底层操作系统、硬件设备或其他编程语言进行交互。本地接口常常是通过C或C++编写的,这里就不概述了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值