垃圾收集机制

2022-11-18  本文已影响0人  蓝调_4f2b

一. 垃圾收集算法

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的缺点:

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)对三色标记漏标问题的处理

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
上一篇 下一篇

猜你喜欢

热点阅读