总结JVM的垃圾回收机制

前言

本文介绍JVM垃圾回收相关的知识。主要内容有:判断对象是否存活、对象引用的类型、垃圾回收算法、垃圾回收器。

判断对象是否存活

垃圾回收主要是对对象进行回收,故首先需要找出那些不再存活的对象,主要有两种方法。

引用计数法

用一个引用值标记对象被引用的次数,当引用值为0,表明对象可被回收。

优点:实现简单、效率高

缺点:如果对象之间存在相互引用,引用值无法归零,无法回收对象。

可达性分析

判断对象是否在GCRoot的引用路径上,如果没有,表明对象可被回收。

对象引用的类型

对象有四种引用类型。强软弱虚,用男人女人老人死人来类比,应该很好记忆。

强引用

一般我们new出来的对象

软引用

非必需的对象,在oom即将发生之前被回收

弱引用

非必需的对象,在下一次gc时被回收

虚引用

任何时候都可以被gc

垃圾回收算法

清楚哪些对象需要被回收后,下一步操作就是回收对象,这里引出回收对象的几种算法。

标记清除法

标记待回收对象,直接清除。

优点:效率高

缺点:内存不规整(有碎片)

复制算法

内存分两块,第一块标记存活对象,然后复制到第二块,最后清空第一块。

优点:内存规整

缺点:空间浪费、复制耗时

标记整理法

标记待回收对象,直接清除,然后整理存活对象。

优点:内存规整

缺点:整理耗时

分代算法

堆内存划分为新生代和老年代,新生代由eden和survivor区(两块)组成,对象在eden区创建,经过gc后还存活,就移入survivor区。经过n(默认16)次gc后还存活,移入老年代。新生代和老年代会使用不同的垃圾回收方式。一般来说,新生代采用复制算法,因为大部分对象在gc后会被回收,剩下的存活对象较少,复制消耗低。由于survivor区分为两块。当gc发生时,存活对象(在eden和其中一块survivor区中)被复制到survivor中的一块,另外一块被清除。

垃圾回收器

垃圾回收算法是一种思路,而垃圾收集器是这些算法的具体实现。根据具体的业务场景选择合适的垃圾回收器。

新生代使用:Serial/ParNew/Parallel Scavenge

老年代使用:Serial Old/Parallel Old/CMS/G1

Serial(复制)

单线程,适合单CPU,gc线程执行时,应用线程暂停,即Stop The World现象。

ParNew(复制)

Serial的多线程版本,适合多CPU

Parallel Scavenge(复制)

和ParNew类似,区别是该回收器关注吞吐量的提高,即尽量的减少垃圾收集时间,但并不意味着减少STW的时间,主要适合一些对短暂停顿时间不敏感的程序,如后台的一些计算、批处理。

Serial Old(标记整理)

Serial的老年代版本

Parallel Old(标记整理)

Parallel Scavenge的老年代版本

CMS(标记清除)

CMS的出现是为了减少停顿时间的,适用于用户交互频繁的程序,注重用户体验。主要有几个步骤。

  • 初始标记:标记和GCRoots直接关联的对象,停顿时间较短

  • 并发标记:标记待清除对象,gc线程和应用线程并发执行

  • 重新标记:并发标记阶段由于应用线程是执行的,所以还需要再次进行标记,停顿时间较短

  • 并发清除:对标记的对象进行清除,gc线程和应用线程并发执行,由于是标记清除法,故内存不规整

G1

只需要G1即可同时管理新生代和老年代,使用标记整理法,块与块之间使用复制算法。兼顾停顿时间和吞吐量。

感想

JVM还是很有必要了解的,装装逼也是可以的。最近在看一本叫《深度工作》的书,让我重新意识到专注的重要性,这篇文章的知识点和整理是我在心无杂念,高度专注的前提下完成的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值