垃圾收集器与内存分配策略(中)

3.HotSpot的算法实现

在HotSpot虚拟机上实现对象存活判定算法和垃圾收集算法时,必须对算法的执行效率有严格的考量,才能保证虚拟机高效运行。
(1)枚举根节点
可达性分析对执行时间的敏感还体现在GC停顿上,因为这项分析工作必须在一个能确保一致性的快照中进行——这里“一致性”的意识是指在整个分析期间整个执行系统看起来像被冻结在某个时间点上,不可以出现分析过程中对象引用关系还在不断变化的情况,该点不满足的话分析结果准确性就无法得到保证。
在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用。这样GC在扫描时就可以直接得知哪些地方存放着对象引用信息了。
(2)安全点
在OopMap的协助下,HotSpot可以快速且准确地完成GC Roots枚举,但是一个很现实的问题随之而来:可能导致引用关系变化,或者说OopMap内容变化的指令非常多,如果为每一条指令都生成对应的OopMap,那将会需要大量的额外空间,这样GC的空间成本将会变得很高。
HotSpot的确没有为每条指令都生成OopMap,只是在“特定的位置”记录了这些信息,这些位置称为安全点,即程序执行时并非在所有地方都能停顿下来开始GC,只有在到达安全点时才能暂停
安全点的选定基本上时以长袖“是否具有让程序长时间执行的特征”为标准进行选定的——因为每条指令执行的时间都非常短暂,程序不太可能因为指令流长度太长这个原因而过长时间运行,“长时间执行”的最明显特征就是指令序列复用,例如方法调用、循环跳转、异常跳转等。
关于安全点,另一个需要考虑的问题是如何在GC发生时让所有线程(这里不包括执行JNI调用的线程)都“跑”到最近的安全点上再停顿下来。这里有两种方案可供选择:抢先式中断和主动式中断
·抢先式中断不需要线程的执行代码主动去配合,再GC发生时,首先把所有线程全部中断,如果发现有线程中断的地方不在安全点上,就恢复线程,让它“跑”到安全点上。现在几乎没有虚拟机实现采用抢先式中断来暂停线程从而响应GC事件
·主动式中断的思想时当GC需要中断线程的时候,不直接对线程操作,仅仅只是简单的设置一个标志,各个线程执行时主动去轮询这个标志,发现中断标志为真时就自己中断挂起。
(3)安全区域
安全区域是指在一段代码片段之中,引用关系不会发生发生变化。在这个区域中的任意地方开始GC都是安全的。

4.垃圾收集器

如果说收集算法时内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。
虽然我们是在对各个收集器进行比较,但并非为了挑选出一个最好的收集器,因为直到现在为止还没有最好的收集器出现,更加没有万能的收集器,所以我们选择的只是对具体应用最合适的收集器。
(1)Serial收集器
Serial收集器是最基本、发展历史最悠久的收集器,曾经是虚拟机新生代收集的唯一选择。这个收集器是一个单线程的收集器,但它的“单线程”的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,知道它收集结束。
Serial收集器优于其他收集器的地方:简单而高效(与其他收集器的单线程比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。
(2)ParNew收集器
ParNew收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一样。
ParNew收集器除了多线程收集之外,其他与Serial收集器相比并没有太多创新之处,但它却是许多运行在Server模式下的虚拟机中首选的新生代收集器,其中有一个与性能无关但是很重要的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作。
(3)Parallel Scavenge收集器
Parallel Scavenge收集器是一个新生代收集器,它是使用复制算法的收集器。
Parallel Scavenge收集器的主要目标则是达到一个可控制的吞吐量。
(4)Serial Old收集器
Serial Old收集器是Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法。这个收集器的主要意义也是在于给Client模式下的虚拟机使用。如果在Server模式下,那么它主要还有两大用途:一种用途是在JDK1.5以及以前的版本中与Parallel Scavenge收集器搭配使用,另一种用途就是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。
(5)Parallel Old收集器
Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
(6)CMS收集器
CMS收集器是一种以获取最短回收停顿时间为目标的收集器,目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。
CMS收集器是基于“标记-清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,整个过程分为4个步骤,包括:
·初始标记
·并发标记
·重新标记
·并发清除
CMS收集器的内存回收过程是与用户线程一起并发执行的。
CMS还远达不到完美的程度,它有以下3个明显的缺点:
·CMS收集器对CPU资源非常敏感
·CMS收集器无法处理浮动垃圾
·CMS收集器收集结束时会有大量空间碎片产生
(7)G1收集器
G1收集器时当今收集器技术发展最前沿成果之一。
G1是一款面向服务端应用的垃圾收集器。HotSpot开发团队赋予它的使命是(在比较长期的)未来可以替换掉JDK1.5中发布的CMS收集器,与其他GC收集器,G1具备如下特点:
·并行与并发:G1收集器可以通过并发的方式让Java程序继续执行。
·分代收集:G1收集器能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。
·空间整合:G1从整体看来是基于“标记-整理”算法实现的收集器,从局部上来看是基于“复制”算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。
·可预测的停顿:G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。
G1收集器的运作过程大致可划分为以下几个步骤:
·初始标记
·并发标记
·最终标记
·筛选回收

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值