JVM(垃圾回收机制 ---- GC)

啥是垃圾?

不再使用的内存


啥是垃圾回收机制?

自动释放不用的内存
注意: GC 主要是针对 堆 进行的
GC的基本操作单位是 对象, 即GC'回收的是整个对象都不使用的情况


GC 的优缺点

好处: 省心, 写代码简单, 不易出错

缺点: 需要消耗额外资源, 有额外性能开销 , 此外, 易触发 STW 问题

STW 问题

Stop The World

如果内存中垃圾很多, 此时触发一次 GC 操作, 开销可能非常大, 还可能会触发一些锁操作, 因此会导致业务代码无法正常执行


GC 实际工作过程

  1. 找到垃圾 / 判定垃圾
  2. 进行垃圾 (对象) 的释放

找到垃圾 / 判定垃圾

关键是看这个有没有引用 "指向" 它, 没有引用指向的对象, 自然不可能被用到, 就是垃圾了
两种典型实现:

  1. 引用计数 (py / php 做法)
    给每个对象分配一个计数器, 每次创建一个引用指向该对象, 计数器加一, 每次删除一个该对象的引用, 计数器减一, 当计数器为0, 该对象自然就是垃圾了

问题 :

  • 内存空间利用率低 (计数器本身需要存储)
  • 存在循环引用的问题 (py / php 使用引用计数, 需要搭配其他机制来避免循环引用)
  1. 可达性分析 (Java 做法)
    将整个 Java 中所有的对象, 通过 链式 / 树形 结构, 整体给串起来
    可达性分析,就是把所有的对象被组织起来的结构视为树, 从树的根节点出发, 遍历树, 所有能被访问到的对象, 标记成 "可达"
    JVM 再比对自己手里的对象名单, 将不可达的对象进行回收(每次 new 一个对象的时候, JVM 都会有记录)
  • 可达性分析类似树遍历, 相对于引用计数会慢一些 (因此不必一直执行, 每隔一段时间执行一次就ok ---- "虽迟但到" )
  • 可达性分析遍历的起点 ---- GCroots (一个代码中会有很多起点, 每个起点往下扫一遍, 就完成一次分析)

清理垃圾 (此处为几种垃圾回收算法)

  1. 标记清理

    简单粗暴的做法, 如果灰色区域为垃圾, 白色不是, 则直接清除

    问题:
  • 会产生零散的内存碎片
    2.复制算法

把内存空间均分成两份, 每次将不是垃圾的对象复制到另外一边, 然后把整个含垃圾的区域清理掉
问题 :

  • 空间利用率低 (每次只能用到一半空间)
  • 如果垃圾少, 有效对象多, 复制成本就会很大
  1. 整理标记

    类似顺序表删除中间元素, 将不是垃圾的对象从前往后依次排开, 清理剩余空间
  • 保证了空间利用率, 也解决了内存碎片问题
  • 显而易见, 本做法效率也不高

分代回收

基于上述基本策略, 搞了一个符合策略 "分代回收"

历史基本规律: 如果一个东西存在的时间比较长, 那么大概率还会继续长时间存在下去

该规律对于 Java 同样有效, Java 对象要么生命周期特别长, 要么特别短

引入概念: 年龄 ---- 熬过 GC 的轮次 (没被清理)
将堆分成一系列区域

Minor GC : 新生代 GC

Full GC : 老年代 GC

  • 刚创建的对象, 年龄为 0 ,放到伊甸区
  • 熬过一轮 GC ,放入幸存区 (复制算法)
  • 幸存区中对象, 周期性接收 GC 考验, 如果变成垃圾, 就被释放, 如果不是垃圾, 就拷贝到另外一个幸存区 (俩幸存区同一时刻只使用一个), 在二者间来回拷贝 (复制算法)
  • 在幸存区中经过了多轮考验后, 进入老年代
  • 老年代也要周期性 GC 扫描, 只是频率更低
  • 如果老年代的对象是垃圾了, 使用标记整理的方式进行释放
相关推荐
无尽的大道12 小时前
Java反射原理及其性能优化
jvm·性能优化
AAA 建材批发王哥(天道酬勤)18 小时前
JVM 由多个模块组成,每个模块负责特定的功能
jvm
JavaNice哥1 天前
1初识别jvm
jvm
涛粒子1 天前
JVM垃圾回收详解
jvm
YUJIANYUE1 天前
PHP将指定文件夹下多csv文件[即多表]导入到sqlite单文件
jvm·sqlite·php
逊嘘1 天前
【Java语言】抽象类与接口
java·开发语言·jvm
鱼跃鹰飞1 天前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试
王佑辉1 天前
【jvm】Major GC
jvm
阿维的博客日记1 天前
jvm学习笔记-轻量级锁内存模型
jvm·cas·轻量级锁