Appearance
概述
垃圾回收(Garbage Collector,GC)算是高级语言的标品,让开发人员把关注重点放到程序设计上,大大增加了增加了开发的效率,同时也提升的程序运行的安全性,避免一些内存泄露的场景,但也带来一些性能损失和放弃内存控制的精确性
实现方式
- 可达性分析 从根节点出发,根据引用关系来搜索,所经过的路径称为引用链,当一个对象没有被任何引用链访问到时,证明此对象不是活跃的,可以被回收,JVM、.NET、GoLang的垃圾回收都有基于此方式的实现
- 引用计数器 对象被引用一次记录加一,去除引用次数减一,内存回收时不需要SWT,与程序实时交互,引用计数为0时可以直接被知道
根节点
在gc的世界里根是可达性分析的起点,在JAVA语言中可以作为GCroot的对象有
- 虚拟机栈中(栈帧中的本地变量表)引用对象
- 方法区中的静态属性引用对象
- 方法区中常量引用对象
- 本地方法中JNI(Native)引用对象 是否可以作为根的判断依据:程序是否可以直接引用该对向(譬如调用栈中的变量指针) 同时还要注意的是:不同垃圾回收器旋转GC root的范围也是不一样的
并行回收&&串行回收
根据垃圾回收的运行方式不同,GC 可以分为三类:
- 串行执行:垃圾回收器执行的时候应用程序挂起,串行执行指的是垃圾回收器有且仅有一个后台线程执行垃圾对象的识别和回收;
- 并行执行:垃圾回收器执行的时候应用程序挂起,但是在暂停期间会有多个线程进行识别和回收,可以减少垃圾回收时间;
- 并发执行:垃圾回收器执行期间,应用程序不用挂起正常运行(当然在某些必要的情况下垃圾回收器还是需要挂起的);
上面并发和并行容易混淆,因为在Java 中,我们提到的并发天然会联想到是「同一类多个线程」执行「同一类任务」,在 GC 中,并发描述的是「GC 线程」和「应用线程」一起工作。 当我们说到某种垃圾回收器支持并发时,并不意味着在垃圾回收的过程中都是并发的,譬如,G1和 CMS 垃圾回收器支持并发标记,但是在对象转移、引用处理、符号表和字符串表处理、类卸载时,是不支持并发的。总之,并发的表述具有「阶段性」。
垃圾回收算法
标记-清除(Mark-Sweep): 最基础的垃圾回收算法,分为标记和清除两个阶段。首先标记出所有需要回收的对象,然后统一回收这些对象。
标记-整理(Mark-Compact): 在标记-清除的基础上增加了一个整理阶段,将存活的对象移动到内存的一端,从而减少内存碎片。
复制(Copying): 将内存分为两个半区,每次只使用其中一个半区。当一个半区满了之后,将存活的对象复制到另一个半区,然后清理已使用的半区。
增量(Incremental): 将垃圾回收过程分成多个小步骤,每次执行一小部分,以减少程序的停顿时间。
分代(Generational): 基于对象生命周期的不同,将内存分为不同的代(如新生代和老年代)。新生代的对象存活率低,回收频繁;老年代的对象存活率高,回收较少。
并发(Concurrent): 垃圾回收器与应用程序线程并发执行,以减少程序的停顿时间。
并行(Parallel): 垃圾回收器使用多个线程同时进行垃圾回收,以提高回收效率。
垃圾回收器
G1(Garbage-First): 一种服务器端的垃圾回收器,旨在提供可预测的停顿时间,适用于多处理器机器。
ZGC(z garbage collector): 一种可扩展的低延迟垃圾回收器,旨在处理大量内存,同时保持低延迟。
CMS(Concurrent Mark Sweep): 是Java虚拟机(JVM)中的一种老年代垃圾收集器,主要目标是减少垃圾收集时的应用程序停顿(STW)时间 一种可扩展的低延迟垃圾回收器,旨在处理大量内存,同时保持低延迟。
Shenandoah: 一种低停顿时间的垃圾回收器,允许应用程序线程在大部分垃圾回收阶段继续执行。
Epsilon: 一种无操作垃圾回收器,实际上不进行任何垃圾回收工作,用于性能测试。