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


原始快照要破坏的是第二个条件,当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后,再将这些记录过的引用关系中的灰色对象为根,重新扫描一次 。这也可以简化理解为,无论引用关系删除与否,都会按照刚刚开始扫描那一刻的对象图快照来进行搜索 。
以上无论是对引用关系记录的插入还是删除,虚拟机的记录操作都是通过写屏障实现的 。在虚拟机中,增量更新和原始快照这两种解决方案都有实际应用,譬如,CMS是基于增量更新来做并发标记的,G1、则是用原始快照来实现 。
垃圾收集器
展示了七种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用,图中收集器所处的区域,则表示它是属于新代收集器抑或是老年代收集器 。
收集器
收集器是最基础、历史最悠久的收集器,曾经(在JDK 1.3.1之前)是虚拟机新生代收集器的唯一选择 。大家只看名字就能够猜到,这个收集器是一个单线程工作的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束 。
似乎已经把收集器描述成一个最早出现,但目前已经老而无用,食之无味,弃之可惜的“鸡肋”了,但事实上,迄今为止,它依然是虚拟机运行在客户端模式下的默认新生代收集器,有着优于其他收集器的地方,那就是简单而高效(与其他收集器的单线程相比),对于内存资源受限的环境,它是所有收集器里额外内存消耗( )最小的;对于单核处理器或处理器核心数较少的环境来说,收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率 。
收集器
收集器实质上是收集器的多线程并行版本,除了同时使用多条线程进行垃圾收集之外,其余的行为包括收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与收集器完全一致,在实现上这两种收集器也共用了相当多的代码 。收集器的工作过程如图
收集器除了支持多线程并行收集之外,其他与收集器相比并没有太多创新之处,但它却是不少运行在服务端模式下的虚拟机,尤其是JDK 7之前的遗留系统中首选的新生代收集器,其中有一个与功能、性能无关但其实很重要的原因是:除了收集器外,目前只有它能与CMS收集器配合工作 。
收集器在单核心处理器的环境中绝对不会有比收集器更好的效果 。当然,随着可以被使用的处理器核心数量的增加,对于垃圾收集时系统资源的高效利用还是很有好处的 。它默认开启的收集线程数与处理器核心数量相同,在处理器核心非常多(譬如32个,现在CPU都是多核加超线程设计,服务器达到或超过32个逻辑核心的情况非常普遍)的环境中,可以使用-XX:参数来限制垃圾收集的线程数 。
收集器
收集器也是一款新生代收集器,它同样是基于标记-复制算法实现的收集器,也是能够并行收集的多线程收集器…… 的诸多特性从表面上看和非常相似,那它有什么特别之处呢?
收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而 收集器的目标则是达到一个可控制的吞吐量() 。所谓吞吐量就是处理器用于运行用户代码的时间与处理器总消耗时间的比值,即:
如果虚拟机完成某个任务,用户代码加上垃圾收集总共耗费了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99% 。停顿时间越短就越适合需要与用户交互或需要保证服务响应质量的程序,良好的响应速度能提升用户体验;而高吞吐量则可以最高效率地利用处理器资源,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的分析任务 。