Java垃圾收集器及收集算法总结

当我们学习JVM的时候,肯定最开始学习的就是JVM的内存和垃圾回收相关的知识。最近我也在学习,所以把自己学习的东西总结分享一下:

首先,在了解JVM垃圾收集器之前,我们得了解一下垃圾收集算法相关的知识。

一、如何判断一个对象是否存活?

JVM判断一个对象是否存活的算法有两种:

1、引用计数器算法

这个算法的原理就是给每个对象分配一个计数器,当有其他对象引用它的时候计数器加1,当引用失效的时候计数器减1。当一个对象的引用计数器为零的时候代表这个对象可以被回收。缺点:无法解决对象之间相互循环引用的问题

2、可达性分析算法

这个算法的原理就是JVM选定一些对象为起始点,这些对象叫做“GC Roots”,一般情况下这些起始点都是虚拟机中引用的对象或者方法区中类静态属性的引用对象或者常量。从这些起始点开始向下搜索,搜索走过的路径记录下来,称作引用链,当一个对象没有任何引用链可以到达的时候,这个对象就被认为已经死亡,可以被回收。

二、如何对已经'死亡'的对象进行回收?

目前JVM支持的垃圾收集算法有4种,其实严格来讲有3种。

1、标记-清除算法

这个算法的原理就是利用之前判断对象是否存活的算法进行判断,当对象被判定死亡的情况下,对死亡的对象进行标记,标记完成后对所有标记的对象进行回收处理。缺点:效率低下,标记和清除2个过程的效率都不高,而且还会产生大量的不连续的内存碎片。

1、复制算法

这个算法的原理就是将内存分为大小相同的两部分,每次只使用其中一部分,当使用的这部分的内存用完的时候,将这个部分上的存活对象全部复制到另一个未使用的内存部分,然后将当前内存部分全部清除。这样的算法得到了效率的提示,但是却付出代价为缩小内存为原来的一半。

3、标记-整理算法

这个算法的原理就是在标记-清除算法之后,标记完成了不是立即清除,而是对存活的对象进行整理,把存活的对象保存在连续的空间上,然后把其他空间全部回收。

4、分代收集算法

这个算法其实是其他算法的组合使用,把JVM的堆内存分为新生代和老年代两部分,对每个部分使用不同的收集算法,新生代使用的是复制算法,因为新生代的对象跟新快而且每次清除的空间比较大,效率相对比较高。老年代的对象一般存活的都比较久,而且回收频率也相对少,所以使用标记-整理算法。

三、有哪些垃圾回收器?

1、Serial垃圾回收器

Serial是最基本的垃圾回收器。它是单线程的垃圾回收器。它使用的是复制算法,所以它适用于新生代的垃圾回收。但是它的缺点很明显,就是在回收的时候,必须停止所有用户进程。

2、ParNew垃圾收集器

ParNew其实就是Serial的多线程版本,在收集算法和对象分配规则、回收策略等都与Serial相同。他们都是新生代的回收器。

3、Parallel Scanvenge垃圾回收器

Parallel Scanvenge是一个新生代收集器,他也是使用复制算法,也是多线程,看上去和ParNew相同,但是他们的关注点不同,Parallel Scanvenge收集器的关注点是达到一个可控制的吞吐量。吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)。虚拟机总共运行了100分钟,垃圾收集器花了1分钟,那么吞吐量就是99%。

4、Serial Old垃圾收集器

Serial Old 是Serial的老年代版本,他也是单线程的收集器,使用标记-整理算法。他与Serial的相同之处就是给在Client模式下的虚拟机使用。

5、Parallel Old垃圾收集器

Parallel Old是Parallel Scanvenge的老年代版本,使用多线程和标记-整理算法。他与Parallel Scanvenge结合使用,吞吐量优先的收集器就有了名副其实的组合,所以在吞吐量已经CPU资源敏感的场合,都可以优先考虑Parallel Old+Parallel Scanvenge的组合。

6、CMS垃圾收集器

CMS是一种获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者BS系统的服务端上,他们尤为重视响应速度,希望系统停顿时间最短,CMS是基于标记-清除算法的,他的收集过程分位4步:

-初始标记

-并发标记

-重新标记

-并发清除

初始标记和重新标记仍然需要停止用户线程,但是初始标记只是标记一下GC Roots能直接关联到的对象,速度很快。并发标记就是进行GC  Roots Tracing 的过程,重新标记是为了修正并发标记期间因为用户程序继续运作而导致标记产生变动的那一部分对象的标记记录。由于整个过程中,并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以CMS收集器的内存回收过程是与用户线程一起并发执行的。

他的缺点也很明显,首先它使用标记-清除算法,会产生大量内存碎片,其次他虽然缩短用户线程停顿时间,但是他占用了一部分线程资源,导致应用程序变慢。最后他无法处理浮动垃圾,由于他在并发标记的阶段,用户线程还在运行,还会有新垃圾的产生,这一部分垃圾出现在标记过程之后。CMS无法在当次收集中处理。

7、G1(Garbage-First)垃圾收集器

G1垃圾收集器是目前垃圾收集器最前沿的成果之一,G1是一款面向服务器端应用的垃圾收集器。G1有以下几个特点

-并发与并行:G1能充分利用多CPU和多核环境下的硬件优势,使用多个CPU来缩短用户线程停顿时间。

-分代收集:G1能独立完成分代收集。它集标记-整理和复制于一体。

-空间整合:G1在运作期间不会产生内存空间碎片,收集后能提供规整的内存空间。比CMS的标记-清除的优势在于不产生空间碎片。

-可预测的停顿:G1相比于CMS的另一个优势就是建立可预测的停顿时间模型,让使用者指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过M毫秒。

G1收集器把整个Java堆划分为多个大小相等的独立区域,虽然还保留新生代和老年代的概念,但是新生代和老年代不再是物理隔离,他们都是一部分的区域的集合(不需要连续)。

G1跟踪每个区域里面垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的区域,这种回收方式,保证G1收集器在有限时间内可以获取尽可能高的回收效率。

G1的收集过程也分为4步

-初始标记

-并发标记

-最终标记

-筛选回收

他的这几个步骤跟CMS的有很多相似之处。由于目前G1成熟版本发布时间比较短。所以还没有很多实际应用的考验。


好了到这里差不多JVM的垃圾回收算法和垃圾收集器介绍的差不多了,以上很多内容都是参考《深入理解Java虚拟机》-周志明。所以如果大家想更多的了解JVM的话可以购买书籍去阅读

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值