jvm GC算法类型&垃圾收集器种类详解一条龙


总结下gc相关的内容,也是面试中常问的。

一.jvm体系概览

在这里插入图片描述
其中,灰色是线程私有空间;黄色(方法区和堆区)是公有空间,GC就跟这俩有关系。

几个概念:
方法区:是jvm的实现规范,具体的实现在1.7及以前版本是永久代,在1.8的时候改为了元空间。

  • 堆内存:指的是图中堆得大小;我们的java代码运行时对象都存这里;
  • 非堆内存(Non-heap memory):所有方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法 的代码都在非堆内存中;简单来说就是jvm自己使用的;
  • 堆外内存:比如使用java.nio.DirectByteBuffer对象进行堆外内存的管理和使用

二.如何确定垃圾

1.引用计数
此方法存在循环引用的问题,导致内存泄漏,不被使用。
2.GC Roots(枚举根节点做可达性分析)
在这里插入图片描述
如上图种的对象C,此对象没有被GC Roots节点引用,就是可回收垃圾。
在这里插入图片描述
object5/6/7虽然内部引用,但是没有被GC Roots,也是垃圾。
那么,什么的东西才可以作为GC Roots?
所谓GC Roots,必须是一组活跃的引用。有4种类型:
1.虚拟机栈(栈帧中的局部变量区,也叫局部变量表)中引用的对象;
2.本地方法栈中JNI(native方法)的引用的对象;
3.方法区中,类的静态属性引用的对象;
4.方法区中,常量引用的对象。

三.常见的垃圾回收算法

4种:引用计数;复制;标记清除(Mark-Sweep);标记整理(Mark-Compact);
下面详细解析:
1. 引用计数
在这里插入图片描述
缺点:a.每次对对象进行赋值时,都需要维护引用计数器,且计数器本身也有一定的消耗;
b.较难处理循环引用。
jvm一般不采用这种时间方式。
2. 复制
发生在年轻代。
在这里插入图片描述
复制之后有交换,谁空谁是To。 详细如下(复制->清空->互换):
a.Eden和From复,制到To,年龄+1
首先,当Eden区满时,会触发第一次gc,把还活着的对象,复制到from区;当Eden区再次发生gc时,会扫描Eden和From这两个区域,对这两个区域进行垃圾回收,把还活着的对象,直接复制到To区(如果有对象年龄达到老年标准,则复制到老年代),同时把对象的年龄+1。
b.清空Eden和From
然后,清空Eden和From种的对象;
c.To和From互换
最后,To和From互换,此时From为空,变为To区;原来的To,变为下一次gc时的From区;部分对象会在From和To之间来回复制,交换15次(由jvm参数MaxTenuringThreshold决定,这个参数默认值是15)之后,如果对象还存活,就存入到老年代。
复制优点:整体复制,没有产生碎片;
复制缺点:浪费空间;并且有大对象时,比较耗时;
3. 标记清除(Mark-Sweep)
发生在老年代。在这里插入图片描述
优点:没有复制,节省空间;
缺点:产生内存碎片;
4. 标记压缩整理(Mark-Compact)
发生在老年代。
在这里插入图片描述
优点:在标记清除的基础上,增加滑动,解决了碎片问题;
缺点:滑动(移动)对象需要成本。

四.垃圾回收器种类

上述谈到的4种垃圾回收算法,是内存回收的方法论,垃圾收集器就是算法的落地实现
目前还没有完美的收集器,更加没有万能的收集器出现,只能针对具体情况,使用合适的收集器,进行分代收集。
4种主要的垃圾收集器:串行(Serial),并行(Parallel),并发(CMS),G1
java11/12还有一种新的,ZGC,太新,暂时不分析。
在这里插入图片描述
1.串行(Serial) 垃圾回收器
它针对单线程环境设计,且只使用一个线程进行垃圾回收,会暂停所有用户线程,所以不适合服务器环境。
形象解释:大家在餐厅用餐(用户线程),来了一位员工阿姨(垃圾回收线程),说我们要打扫卫生了,请大家先暂停用餐,打扫完再继续吃饭。
2.并行(Parallel) 垃圾回收器:
有多个垃圾收集线程并行工作,此时用户线程也是暂停的;适用于科学计算/大数据后台处理等,和前台若交互场景;
形象解释:大家在餐厅用餐(用户线程),来了多个员工阿姨(垃圾回收线程),说我们要打扫卫生了,请大家先暂停用餐,打扫完再继续吃饭。
3.CMS (并发标记清除)
用户线程和垃圾收集线程同时执行(不一定是并行,也可能是交替执行),不需要停止用户线程;互联网公司多用此种方式,适用于对响应时间有要求的公司。
4.G1(Garbage First)
在这里插入图片描述
jdk7出现,jdk9中代替CMS成为默认垃圾收集器。是一款面向服务端应用的垃圾收集器,应用在多处理器和大容量内存环境种。在实现高吞吐量的同时,尽可能满足垃圾收集暂停时间的要求。
特点:
化整为零,不需要全内存扫描,只需要按照区域进行扫描即可;
G1充分利用多cpu,多核环境的硬件优势,缩短停顿时间;
G1整体上采用标记整理算法,局部采用复制算法,不会产生内存碎片
G1不在区分新生代和老年代,把内存划分为多个子区域(region,1-32M不等,默认2048个区域),像围棋的棋盘一样;
局部逻辑上区分新生代和老年代,也就是说,每个小region有可能是新生代,有可能是老年代,并且还可以随时间进行变化。
G1在停顿时间上添加了预测机制,用户可以指定期望的停顿时间;

五.垃圾收集器与各内存代对应关系

上述4种垃圾收集器具体可以细化为如下7中类型:
在这里插入图片描述

在这里插入图片描述

六.引用类型和垃圾回收

4种引用类型:强/软/弱/虚
在这里插入图片描述
引用类型与垃圾回收的关系:
在这里插入图片描述
引用:就是常见的普通对象应用,jmv垃圾回收时,即使出现OOM也不进行垃圾回收,死都不收;
引用:当内存充足时,不被回收;内存紧张时,会被回收;通常用在对内存敏感的程序种,比如高速缓存种,存了大量图片,当内存不够时,可以回收缓存种的一些图片对象。
在这里插入图片描述
引用:必定被回收;
在这里插入图片描述
WeakHashMap(Mybatis缓存大量使用)。
引用:幽灵引用(PhantomReference),必定被回收。必须和引用队列(ReferenceQueque)结合使用,**被回收之后,放到应用队列,**实际还没有真正被回收。
虚引用的主要作用时跟踪垃圾被回收的状态;就是这个对象被垃圾回收的时候收到一个系统通知或者后续添加进一步的处理。
java技术允许使用finaliz()方法,在垃圾收集器将对象从内存中清除之前做必要的清理工作。
就是jvm允许我们在对象销毁之后,做一些我们自己想做的事情。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值