美文网首页
垃圾收集机制

垃圾收集机制

作者: 蓝调_4f2b | 来源:发表于2022-11-18 00:36 被阅读0次

一. 垃圾收集算法

1. 标记-复制算法

一般应用于年轻代中,将内存分为相同大小的两块,每次使用其中一块;本次使用完成后,将存活对象复制到另一侧,并清空这块内存。
问题:该种方式浪费空间

2. 标记-清除算法

一般应用于老年代。
(1)标记阶段:标记存活的对象
(2)清除阶段:清除未被标记的对象
(3)问题:效率较低;标记清除后会产生大量不连续空间

3. 标记-整理算法

优点:避免内存碎片产生

二. 垃圾收集器

垃圾收集器使用图.png

1. serial收集器(串行收集器)

(1)使用serial收集器配置:
-XX: +UseSerialGC
-XX: +UseSerialOldGC
(2)串行收集


串行收集示意图.png

注:STW(stop the world)暂停所有用户线程,并开始清理系统垃圾,这样做的原因是防止在垃圾清理过程中对象引用发生变化,产生新的未标记到的垃圾。

2. parallel收集器(JDK8默认)

(1)开启parallel收集器配置:
-XX: +UseParallelGC
-XX: +UseParallelOldGC
(2)并发收集


并发收集.png

3. parNew收集器

与parallel类型,主要区别为可与CMS配合使用

4. CMS垃圾收集器

基于标记-清除算法实现,底层使用写屏障模式
4.1 流程示意图


CMS收集器流程.png

(1)初始标记:执行STW(stop the world),此时用户线程均已停止,垃圾收集器通过引用链分析法找到gc根节点直接引用的对象,该阶段速度极快

User u = new User();  // 对象u为User类的直接引用

(2)并发标记:并发的含义是应用线程与回收线程并发运行,垃圾收集器将接替初始标记到的对象向下一直寻找堆中的引用,由于此时引用链变得复杂,这部分标记将使用并发标记;相较于STW标记方式,并发标记兼顾了用户线程的执行与垃圾收集,故此处垃圾收集时间将较长

class Person {
  string p_name;
  int p_id;
}
Person p = new Person("xiaoming", 10);
u.setPerson(p);        // 该引用非直接引用,将在并发标记阶段执行标记

(3)重新标记:修正并发标记期间由于用户行为改变的标记对象,底层使用三色标记法
(4)并发清理:将未标记的对象进行清除
(5)并发重置:重置本次GC标记的数据
(6)CMS的缺点:

  • 对CPU资源较为敏感,并发标记等阶段gc会与用户线程争夺资源
  • 无法处理浮动垃圾,在并发标记和并发清理阶段又产生的垃圾,只能等到下次GC进行处理
  • 底层使用回收算法“标记-清除”导致产生大量碎片,我们可以通过-XX: +UseCMSComputeAtFullCollection,当JVM执行完标记清除后再整理碎片
  • 垃圾收集过程中可能触发concurrent mode failure(并发模式失败):
    在并发标记与并发清理过程中,用户线程将产生新的对象存入老年代,而此时若老年代已满,将激发CMS算法触发full gc(serial old),执行串行STW
    (7)三色标记法(CMS底层算法)
    处理并发标记过程中,对象引用变化的问题;
    会产生漏标的问题,例如以下情况:
class A {
  B b = new B();
  D d = null;
}
class B{
  C c = new C();
  D d = new D();
}
class C {}
public static void main() {
  A a = new A();
  D d = a.b.d;          // 插入读屏障
  a.b.d = null;          // 写屏障
  a.d = d;                // 写屏障
}
三色标记法.png

注:最终不回收黑色/灰色对象,只回收白色对象
(8)对三色标记漏标问题的处理

  • 增量更新方式
    采用缓存记录并发标记过程中扫描的对象,重新标记过程中将从缓存中重新扫描这些对象。


    增量更新方式.png
  • 原始快照方式
    使用缓存方式作为快照集合,将被删除的引用放入集合中记录,并将对象节点标为黑色,成为浮动垃圾,在下轮清理的过程中会清理该种浮动垃圾。
  • 实现增量更新/原始快照方式:写屏障
    给某个对象的成员变量赋值时,在赋值前后进行操作
void oop_field_store(oop* field, oop new_value) {
  pre_write_barrier(field);
  *field = new_value;
  post_write_barrier(field);
}

(9)记忆集与卡表
解决跨代引用问题

5. G1收集器

G1收集器将java堆分为大小相等的多个独立区域(Region),种类为:
Eden区,survive区,old区及Humongous区
其中Humongous区存放占内存过大对象(一个对象超过region50%,默认被放入Humongous区域)
(1)G1收集流程


G1收集流程.png
  • 筛选回收过程:对各个Region回收价值与成本进行排序,依据用户期望GC停顿回收时间制定回收计划(通过-XX:+MaxGCPauseMills修改用户预期停顿阈值),将STW限制在一定时间范围内,增强用户体验
  • 底层采用复制算法回收
  • 优先级列表:考虑gc时间,占用内存空间等
    (2)G1收集算法分类:
  • young GC:计算当前Eden区回收时是否到达设定的时间阈值,不到达该阈值,则继续将对象放入Eden区;到达阈值,则进行一次Young GC
  • mixed GC:回收所有年轻代,部分老年代及Humouongs区域垃圾,是否触发mixed GC由收集阈值确定,阈值的设置通过-XX:InitiatingHeapOccupancyPercent设定。
  • full gc:STW,当老年代完全放满时开始执行,采用单线程进行标记,清理空间
    (3)G1垃圾收集器使用场景:
  • 所用系统的堆中50%以上空间被存活对象占用
  • 对象分配及晋升到老年代的速度变化较大时
  • 垃圾收集时间较长时,比如超过1秒钟
  • 堆内存较大(因为底层使用的是复制算法),超过8GB以上
  • 停顿时间在500ms以内
    注:不同内存推荐使用的算法版本:
  • 堆内存4G以下推荐使用parallel
  • 堆内存4-8G使用CMS+parallel
  • 堆内存8G以上使用G1

相关文章

  • JS垃圾回收机制(内存问题)

    垃圾收集机制理解 垃圾收集机制:释放无用的数据,回收内存。 垃圾收集机制分类:1)自动回收 2)手动回收 垃圾收集...

  • JavaScript之垃圾收集

    垃圾收集 JavaScript 具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。这种垃圾收集机制...

  • javascript垃圾回收与内存泄漏

    垃圾回收机制 自动垃圾收集机制 javascript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程...

  • 垃圾收集与内存泄漏

    垃圾收集机制 与C,C++不同,JavaScript拥有自动垃圾收集机制,垃圾收集器会按照固定的时间间隔,周期性的...

  • 闭包会造成内存泄漏吗?

    前言 在谈内存泄漏这个问题之前先看看JavaScript的垃圾收集机制,JavaScript 具有自动垃圾收集机制...

  • js之内存泄漏

    一、JavaScript 的垃圾收集机制 javascript具有自动垃圾收集机制,也就是说,执行环境会负责管理代...

  • 垃圾收集机制

    JS具有垃圾回收机制 而在c和c++之类的语言中国 开发人员基本任务就是手工跟踪内存的使用情况 这则是造成很多问题...

  • 垃圾收集机制

    一. 垃圾收集算法 1. 标记-复制算法 一般应用于年轻代中,将内存分为相同大小的两块,每次使用其中一块;本次使用...

  • JavaScript内存管理-标记清除

    JavaScript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。这种垃圾收集机制的原理很简单...

  • Java 内存区域和GC机制

    Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与...

网友评论

      本文标题:垃圾收集机制

      本文链接:https://www.haomeiwen.com/subject/nyvuxdtx.html