JVM的四种垃圾回收算法和七种垃圾收集器

JDK1.8 默认使用 Parallel Scavenge(年轻代) + Serial Old(老年代)垃圾回收(堆+方法区)

垃圾回收都会stop the world,区别在于时间长短,无论是串行还是并行都会挂起用户线程。然而CMS、G1在并发标记的时候不会挂起用户线程,其他时候会挂起。

系统吞吐量有要求时,使用 Parallel Scavenge垃圾收集器。

扫描对象比复制对象省时得多!

 GC ROOT对象可达

  1. 栈中引用的对象
  2. 方法区类的静态属性引用的对象
  3. 方法区中的常量的引用对象
  4. 本地方法栈的JNI的引用对象

垃圾回收算法发展历程

标记-清理 ——> 复制算法 ——> 标记-整理  ——> 分代收集

垃圾回收算法

标记-清理

标记-清除算法

老年代回收垃圾算法,分为标记和清除两个阶段,先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象。

缺点:标记和清除两个过程效率都不高;标记清除之后会产生大量不连续的内存碎片。

为了解决标记清除算法内存碎片化严重的缺陷,提出了复制算法。 

复制算法

复制算法

将可用的内存分成两份,每次使用其中一块,当这块回收之后把未回收的复制到另一块内存中,然后把使用的清除。这种算法运行简单,解决了标记-清除算法的碎片问题,但是这种算法代价过高,需要将可用内存缩小一半,对象存活率较高时,需要持续的复制工作,效率比较低。

复制算法.png

标记-整理算法

结合了以上两个算法,为了避免缺陷而提出。标记阶段和标记清理算法相同,标记后不是清理对象,而是将存活对象移向内存的一端,然后清除端边界外的对象。 

标记整理算法.png

分代收集

把堆内存分为新生代和老年代,新生代又分为 Eden 区、From Survivor 和 To Survivor。一般新生代中的对象基本上都是朝生夕灭的,每次只有少量对象存活,因此采用复制算法,只需要复制那些少量存活的对象就可以完成垃圾收集;老年代中的对象存活率较高,就采用标记-清除和标记-整理算法来进行回收。

相对而言,老年代每次只回收少量对象,回收次数相对少,采用标记整理算法。

  1. 对象的内存分配主要在新生代的 Eden Space 和 Survivor Space 的 From Space(Survivor 目前存放对象的那一块),少数情况会直接分配到老年代;
  2. 当新生代的 Eden Space 和 From Space 空间不足时就会发生一次 GC,进行 GC 后,EdenSpace 和 From Space 区的存活对象会被挪到 To Space,然后将 Eden Space 和 FromSpace 进行清理;
  3. 如果 To Space 无法足够存储某个对象,则将这个对象存储到老年代;
  4. 在进行 GC 后,使用的便是 Eden Space 和 To Space 了,如此反复循环;
  5. 当对象在 Survivor 区躲过一次 GC 后,其年龄就会 +1。默认情况下年龄到达 15 的对象会被移到老年代中。

垃圾回收器

serial垃圾回收器

  • 新生代:Serial 垃圾收集器是 JVM 运行在 Client 模式下默认的新生代垃圾收集器;
  • 复制算法 :Serial 是最基本垃圾收集器,使用复制算法,曾经是 JDK1.3.1 之前新生代唯一的垃圾收集器;
  • 单线程:Serial 只会使用一个 CPU 或一条线程去完成垃圾收集工作;
  • 线程暂停:Serial 在进行垃圾收集的时,必须暂停其他所有的工作线程,直到垃圾收集结束;
  • 单线程效率最高:Serial 对于限定单个 CPU 环境来说,没有线程交互的开销,可以获得最高的单线程垃圾收集效率。

ParNew 垃圾回收器

  • 新生代:ParNew 垃圾收集器是很多 JVM 运行在 Server 模式下新生代的默认垃圾收集器;
  • 复制算法 : ParNew 和 Serial 一样使用了复制算法;
  • 多线程 :ParNew 垃圾收集器其实是 Serial 收集器的多线程版本;
  • 线程暂停:ParNew 和 Serial 一样垃圾收集的同时,必须暂停其他所有的工作线程;
  • 默认线程数:ParNew 收集器默认开启和 CPU 数目相同的线程数,可以通过-XX:ParallelGCThreads 参数来限制垃圾收集器的线程数。 

Parallel Scavenge回收器

  • 新生代:Parallel Scavenge 收集器也是一个新生代垃圾收集器;
  • 复制算法:Parallel Scavenge 收集器同样使用复制算法;
  • 多线程 :Parallel Scavenge 收集器也是一个多线程的垃圾收集器;
  • 高吞吐量:Parallel Scavenge 重点关注的是程序达到一个可控制的吞吐量(Thoughput,吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)),高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务;
  • 适用场景:主要适用于在后台运算而不需要太多交互的任务。自适应调节策略也是 ParallelScavenge 收集器与 ParNew 收集器的一个重要区别。

 Serial Old

  • 老年代:Serial Old 是 Serial 垃圾收集器老年代的版本;
  • 标记-整理算法:Serial Old 使用标记-整理算法;
  • 单线程:Serial Old 与 Serial 一样是单线程收集器;
  • Client 模式:JVM 运行在 Client 模式下,Serial Old 是默认的老年代垃圾收集器;
  • Server 模式:JVM 运行在 Server 模式下,Serial Old 主要有两个用途:
  1. 在 JDK1.5 之前版本中与新生代的 Parallel Scavenge 收集器搭配使用;
  2. 作为年老代中使用 CMS 收集器的后备垃圾收集方案。

 Parallel Old垃圾回收器

  • 老年代:Parallel Old 收集器是 Parallel Scavenge 的老年代版本;
  • 标记-整理算法:Parallel Old 收集器使用标记-整理算法;
  • 多线程:Parallel Old 收集器是多线程收集器;
  • JDK1.6:Parallel Old 是 JDK1.6才开始提供的。

 CMS垃圾回收器

  • 老年代:CMS(Concurrent mark sweep)收集器是一种年老代垃圾收集器;
  • 标记-清理算法:和其他年老代使用标记-整理算法,CMS 使用标记-清除算法;
  • 多线程 :CMS 采用的是多线程的标记-清除算法;
  • 停顿时间端: CMS最主要目标是获取最短垃圾回收停顿时间,最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验。 

 G1垃圾回收器

  • 无分代:G1 将新生代,老年代的物理空间划分取消了。这样我们再也不用单独的空间对每个代进行设置了,不用担心每个代内存是否足够;
  • 标记-整理算法:G1 收集器采用标记-整理算法,无内存碎片产生;
  • 分区回收:G1 虽然没有了新生代与老年代的物理限制,但是 G1 采取内存分区策略,将堆内存划分为大小固定的几个独立区域。在分区中,同时存在新生代与老年代; 
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值