深入理解Java虚拟机(五)—— 常见的垃圾回收器

一、Serial收集器

        即串行收集器,该收集器是一个单线程工作的收集器,它在进行垃圾收集时,必须暂停其他所有的工作线程,直到垃圾收集完毕。“Stop The World”是由虚拟机在后台自动发起和结束的,在用户不可知、不可控的情况下停止正常的工作线程,对很多应用程序而言是不可接受的。

        Serial收集器在新生代中运用,采取复制算法暂停所有用户线程,与其对应的是Serial Old收集器,应用于老年代,采用标记-整理算法暂停所有用户线程。

图 1-1 Serial收集器

        Serial收集器相对于其他收集器而言,更为简单高效,是所有收集器里二外内存消耗最小的。

选择Serial收集器参数:

-XX: +UseSerialGC

二、ParNew收集器

        ParNew收集器的本质是Serial收集器的多线程并行版本,除了使用多条线程进行垃圾回收外,其余的都与Serial收集器完全一致,包括Serial收集器的控制参数、收集算法、对象分配规则等。

图 2-1 ParNew收集器

        ParNew收集器有一个特点,如果选用CMS收集器后,新生代默认选用的就是ParNew收集器,也是除了Serial收集器以外唯一能与CMS收集器配合工作的收集器。

选择ParNew收集器参数:

-XX: +UseParNewGC

注:JDK9之后取消了这一控制参数,选用CMS默认的新生代收集器为ParNew,也就是ParNew彻底并入了CMS。

三、Parallel Scavenge收集器

        即常说的“吞吐量优先收集器”,Parallel Scavenge收集器是一款新生代收集器,是基于标记-复制算法实现的,Parallel Scavenge收集器与ParNew非常像,它更关注吞吐量(Throughput)这一指标。

图 3-1 吞吐量计算公式

        高吞吐量可以最高效率的利用处理器资源,吞吐量高,就意味着垃圾收集时间短,而更多的精力投入到程序的主要运算任务上。

Paraller Scavenge 控制参数:

-XX: +UseParallelGC

-XX: GCTimeRatio(吞吐量大小,是垃圾收集时间占总时间的百分比)

-XX: MaxGCPauseMillis(最大垃圾收集停顿时间,收集器尽力保证内存回收花费的时间不超过设定的值)

        Parallel Scavenge还具有自适应的调节策略,通过-XX: +UseAdaptiveSizePolicy 参数控制,当该参数激活后,将不需要人工指定新生代(-Xmn)、Eden与Survivor的比例(-XX: SurvivorRatio),虚拟机会根据当前系统的运行情况收集性能监控信息,动态的调整这些参数以提供最合适的停顿时间或者最大吞吐量。

四、Serial Old收集器

        Serial Old收集器和其名字一样,是Serial收集器的老年代版本,同样是一个单线程的收集器,使用标记-整理算法。

图 4-1 Serial Old 收集器

选择Serial Old收集器参数:

-XX: +UseSerialOldGC

五、Parallel Old 收集器

        Parallel Old收集器时Parallel Scavenge收集器的老年代版本,基于标记-整理算法。

图 5-1 Parallel Old 收集器 

选择 Parallel Old收集器参数:

-XX: +UseParallelOldGC(老年代)

六、 CMS收集器

        CMS收集器全称Concurrent Mark Sweep ,是一种以获取最短回收停顿时间为目标的收集器。使用CMS收集器的应用程序更多的是关注服务的响应速度,希望停顿时间尽可能的短,从而带来更好的用户体验。

        CMS收集器是基于标记-清除算法实现的,运作过程分为四步:

图 6-1 CMS收集器

        其中,初始标记重新标记这两个步骤仍然需要暂停用户线程。

        (1)初始标记:仅仅只标记一下GC ROOTS直接关联的对象,速度很快。

        (2)并发标记:从GC ROOTS的直接关联对象开始遍历整个对象图,耗时虽然长,但是不需要停顿用户线程。

        (3)重新标记:其目的是为了修正并发标记期间,因用户程序继续运行而导致标记变动的那一部分对象。

        (4)并发清除:清理标记阶段判定为死亡的对象。

        CMS使用面广,最主要的优点在于,在最耗时的并发标记与并发清除阶段,CMS无需暂停用户线程,CMS收集器的内存回收过程是可以与用户线程一起并发执行的。

        CMS的优点也为CMS带来了部分负面的影响,由于CMS并发标记和并发清理阶段是和用户线程同时进行的,程序难免会在运行中产生新的垃圾对象,如果这部分的“浮动垃圾”产生在并发标记结束后,那么CMS无法在当次收集中处理掉。

        CMS面临的另一问题是,并发标记虽然不会停止用户线程,但是会占用一部分CPU资源从而导致应用程序变慢,CMS默认启动的回收线程数是  (处理器核心数量+3)/ 4  。当处理器核心数量不足4个时,CMS对程序的影响会变大。

        由于CMS与用户线程同时运行的情况,CMS必须预留足够的内存空间给用户线程使用,因此CMS无法像其他垃圾回收器一样等着老年代几乎被填满时再收集。JDK5默认CMS收集器当老年代使用了68%的空间后被激活,而这一阈值在JDK6时提升到了92%,无论何种阈值,CMS都面临着“并发失败”的情况,即CMS预留空间不足以让程序运行产生的新对象的需要。当出现并发失败的情况时,虚拟机将采用预案:冻结用户线程,启用Serial Old收集器来重新进入老年代回收垃圾,Serial Old的特性造就了停顿时间更长的情况。

-XX: CMSInitiatingOccupancyFraction (调整CMS触发的百分比)

        最后,标记-清除算法的特性,CMS收集结束后会产生打量的内存空间碎片,可能会导致大对象因无法找到连续的内存空间而引发一次Full GC。

七、G1收集器(Garbage First)

        G1应该是垃圾回收器当中重要的里程碑,以往的垃圾回收器关注的范围要么是整个新生代,要么就是整个老年代,而G1可以面向堆内存的任何部分来组成回收集,衡量标准不再是分代,而是哪块内存的垃圾数量最多,回收收益最大。这就是G1收集器的Mixed GC 模式。

        G1虽然保留了新生代和老年代的概念,但是不再坚持固定大小的分代区域划分,而是把堆划分为多个大小相等的独立区域,这些区域被称为Region,每一个Region根据需要,都可以扮演新生代的Eden、Survivor、或者老年代空间。收集器会根据扮演不同角色的Region采用不同策略去处理。Region中还有一类特殊的的Humongous区域,专门存放大对象,G1认为只要大小超过了Region容量一半的对象即为大对象。对于超过整个Region容量的超级大对象,将会被存放在N个Humongous Region区域中。

Region的大小可以通过参数控制,取值范围1MB~32MB:

-XX: G1HeapRegionSize

图 7-1 G1收集器

        G1收集器将Region作为单次回收的最小单元,每次回收的内存空间都是Region大小的整数倍,G1会根据回收价值,维护一个优先级列表,优先回收价值收益最大的Region。

        这里存在一个问题,Region当中可能会存在跨Region引用的对象,G1在这里同样采用了记忆集(挤一)的处理手段,每个Region都维护有自己的记忆集,这些记忆集会记录下别的Region指向自己的指针,并标记指针分别在哪些卡页范围内。简单理解就是,Region维护了一张Key为Region起始地址,Value为卡表的索引号的一张哈希表。

        解决了跨Region引用对象的问题,那么接下来要保证的就是并发过程中,不能被用户线程改变对象的引用关系。G1为每一个Region设计了两个名为TAMS(Top at Mark Start)的指针,把Region中的一部分空间划分出来用于并发回收过程中,用户线程产生的新对象的分配,并发回收时新产生的对象地址都必须在这两个指针的位置以上,G1收集器默认在这个地址上的对象是不纳入回收范围的。

        G1收集器的过程大致分为四步:

        (1)初始标记:仅仅标记GC ROOTS直接关联的对象,短暂的停顿用户线程。

        (2)并发标记:从GC ROOTS开始做可达性分析,递归扫描整个队里的对象,找出要回收的对象。

        (3)最终标记:对用户线程做一次短暂停顿。用于处理并发阶段结束后仍遗留下来的少量的原始快照记录。

        (4)筛选回收:负责更新Region的统计数据,对各个Region的回收价值和成本排序,根据用户期望的停顿时间制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧的Region空间。因涉及存活对象的移动,因此会暂停用户线程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容