“这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战”
🔉引言
接下来,把剩下的垃圾收集器都肝完。
⭐️经典的垃圾收集器
🌟SerialOld收集器
SerialOld
收集器是Serial
的老年代版本,单线程,使用标记整理算法,在服务端模式下,有2
种用途:图如下。
- 与
Parallel Scavenge
收集器配合使用(JDK5
以前) - 作为
CMS
收集失败的预案
🌟ParallelOld收集器
ParallelOld
收集器是Parallel Scavenge
的老年代版本,多线程,使用标记整理算法实现,直到JDK6
才提供,在以前啊,你要是新生代使用Parallel Scavenge
那就会比较尴尬,为啥呢?因为老年代除了SerialOld
你找不到与它配合的了,但由于SerialOld
在服务器上性能的拖累,导致使用Parallel Scavenge
起不到很好的吞吐量效果,另一方面,由于单线程无法充分使用服务器的并行处理能力,导致组合起来还不一定有ParNew
和CMS
组合的效果更优一些。
那在ParallelOld
收集器出现后,这种尴尬场面就没有了,牛郎还是得配织女才行,咳咳。那在吞吐量优先或者处理器资源较为稀缺的场合,我们就可以优先考虑它了,图如下。
🌟CMS收集器
CMS收集器英文名是Concurrent mark sweep
,以最短停顿时间为最终目标,适用于一些延时要求低的应用,这类应用的系统停顿时间尽可能短,以便给用户带来很好的交互体验。
Mark Sweep
一看就知道是基于标记-清除算法的,整个过程一共是4个步骤:
- 初始标记(
CMS inital mark
) - 并发标记(
CMS inital mark
) - 重新标记 (
CMS remark
) - 并发清除(
Concurrent sweep
)
其中初始标记和并发标记,是需要Stop the world
的,初始标记的速度很好,只需要标记与GCRoots
关联的对象就好,并发标记那就耗时较长了,肝什么呢?就把GCRoots
关联的对象都遍历一遍,但不需要暂停用户线程,由于是并发操作,所以难免会出现增量更新的情况,关于增量更新可以点击(传送门)去看看。
最后一步就是清除了,由于不需要暂停用户线程,不需要移动存活对象,所以操作也是并发的,图如下。
CMS收集器的缺点
- 对处理器资源敏感
- 容易产生浮动垃圾
- 容易产生空间碎片
面向并发设计的程序都对处理器资源比较敏感,因为要抽调一部分资源去肝额外的事情,虽不会导致用户线程的停顿,但会占用一部分处理器的处理能力,就会使程序变慢,降低总吞吐量。如果你处理器的核心数多,那当然没问题,但如果核心数低,甚至不足4
个时,那影响就会大了,可能会导致用户程序忽然变得很慢,那为了解决这种情况,虚拟机提供了一种增量式的并发收集器,在并发收集和标记时,动态的交替运行,尽量减少垃圾线程的占用时间。这样虽然延长了垃圾回收的时间,但是对程序的影响就很小了,那理论是很好的,实际并不是很好,所以JDK9
就废弃了。
接下来说第二点,就是由于操作的并行的嘛,用户线程就会持续的产生垃圾,但是有的垃圾出现在标记过程结束后,那就不能在这一阶段回收,这部分就是漏网之鱼了。同样,为了保证用户线程持续运行,就不能等待老年代满才进行垃圾收集,而是要预留一部分内存供并发收集的程序使用,如果预留的程序内存无法满足对象分配的需要,就会出现并发失败的结果,这时虚拟机就会冻结用户线程,使用Serial Old
,这样停顿时间就比较长了。
最后一个介绍过了,想了解的小伙伴可以点击【传送门】。
📝题外话
最受爱戴的人应该是那些对于改善人类和人类生活最有贡献的人。这在原则上讲应该是对的。但是,如果你进一步问这类人是谁,就会遇到不小的麻烦。对于政治领袖,甚至宗教领袖,他们究竟是为善多还是作恶多,向来难以定论。
因此我非常真诚地相信,为社会大众提供最好服务的人,是为大众提供可以用来自我升华的工作,从而间接使人臻于完善的人。这首先适用于伟大的艺术家,其次也适用于科学家。无疑,提升人的思想境界并丰富其内在本质的,并非研究成果,而是追求理解的动力,是那种创造性和感受性的脑力劳动。
第22天,大家加油!