深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法

时间:2023-01-02 09:13:55

在进行垃圾收集之前得先确定哪些对象是死的哪些对象是活的?

引用计数算法

给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,当引用失效时计数器值减1,任何时刻,计数器都为0的对象就是不可能再去使用的。
但是Java语言没有使用引用计数法来管理内存,其中主要原因是很难解决对象之间循环引用的问题。

根搜索算法

通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链,我们就说这个对象不可用。
**
在Java语言中,可作为GC Root的对象包括几种:
1、虚拟机栈(栈帧中本地变量表)中引用的对象
2、方法区中类静态属性引用的对象
3、方法区中常量引用的对象
4、本地方法栈中JNI中引用的对象
**
Java中的引用分为四种:强引用、软引用、弱引用、虚引用
强引用:是指程序代码中普遍存在的,Object o =new Object(),这类的引用,只要强引用存在,垃圾回收器永远不会回收掉被引用的对象。
软引用:用来描述一些还有用,但是并非必须的对象,对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中并进行第二次回收。如果这次回收还是内存不足,才会抛出内存溢出异常。SoftReference。
弱引用:是用来描述非必须对象,他的强度比软引用弱一些,被弱引用关联的对象,只能生存到下一次垃圾收集发生之前。当GC发生时,无论内存是否足够,都会回收掉只被弱引用关联的对象。WeakReference。
虚引用:是最弱的一种引用方式。一个对象是否有虚引用存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是这个对象被回收的时候收到一个系统通知。PhantomReference。

垃圾收集算法

标记清除算法

首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
主要缺点有两个:一是效率问题。二是空间问题。标记清除后产生大量的不连续的碎片。空间碎片太多可能会导致当程序在以后运行过程中如果需要分配较大对象时无法找到足够的连续内存而不得不提前促发再一次GC。
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法

复制算法

将可用内存按容量分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将存活着的对象复制到另一快内存中,然后将已使用的那块内存一次性清理掉。
不用考虑内存碎片问题,但是代价就是内存减半。
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法
现在商用虚拟机都采用这种回收算法来回收新生代。将内存分为一块较大的Eden区和两块较小的Survivor区,每次使用一块Eden和一块Survivor区,回收时将存活的对象一次性复制到没有使用的survivor区,然后清理掉Eden和使用过的Survivor区。Hotspot虚拟机默认Eden和Survivor比例是8:1.

标记整理算法

让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法

分代收集算法

当代商用虚拟机都采用分代收集算法。根据对象生存周期将对象分为新生代和老年代,在新生代中每次GC都会有大量的对象死去,只有少量对象存活,所以采用复制算法。而老年代中因为对象存活率高,没有额外空间对它进行分配担保,就必须使用标记整理算法。

垃圾收集器

Hotspot JVM1.6的收集器
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法
如果两个收集器之间存在连线,说明两个收集器可以搭配使用。

Serial收集器

这个收集器是一个单线程收集器,在它进行垃圾收集的时候,必须暂停其他所有的工作线程,直到它收集结束。
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法
现在依然是虚拟机运行在Client模式下默认新生代收集器。

ParNew收集器

其实就是Serial收集器的多线程版本。除了使用多线程进行GC外,其他都跟Serial一样。
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法
它是许多运行在Server模式下虚拟机中首选的新生代收集器。

Parallel Scavenge 收集器

也是一个新生代收集器,也是采用复制算法,也是多线程收集器。
它的特点是它的关注点和其他收集器不同,CMS等收集器关注点是尽可能缩短垃圾回收时用户线程的停顿时间,而Parallel Scavenge收集器的目标是达到一个可控制的吞吐量。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,吞吐量=运行用户代码时间/(运行用户时间+垃圾收集时间)。
停顿时间越短,越适合和用户交互的程序,良好的相应速度能提高用户体验,而高吞吐量可以最高效率的利用CPU时间,尽可能的完成程序的运算任务,主要适合后台运算而不需要太多交互的任务。

Serial Old 收集器

是Serial收集器的老年代版本,单线程收集器,使用标记整理算法
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法

Parallel Old 收集器

是Parallel Scavenge 收集器的老年代版本,使用多线程和标记整理算法,
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法

CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用都集中在互联网网站和B/S系统的服务器上,这类应用尤其重视系统的响应速度,希望停顿时间最短,获取很好的用户体验。CMS收集器就符合这类需求。
标记清除算法实现,主要包括四步:
1、初始标记
2、并发标记
3、重新标记
4、并发清除
其中初始标记和重新标记仍然需要用户线程停止,初始标记仅仅是标记GC Root能直接关联到的对象,速度很快,并发标记阶段进行GC Roots Tracing的过程,而重新标记是为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段停顿时间比初始阶段长,比并发短。
深入理解JVM虚拟机学习笔记(二)垃圾收集器与垃圾收集算法
优点:并发收集,低停顿。
缺点:对CPU资源非常敏感,无法处理浮动垃圾,标记清除会产生大量内存碎片。

G1收集器

基于标记整理算法实现,非常精确的控制停顿