深入理解java虚拟机学习笔记(二) jvm垃圾收集器和内存分配策略

1.垃圾如何确认

对于大多数语言中判断对象是否存活会采用引用计数法:给对象添加一个引用计数器,当有一个地方引用时,计数器就加1,当引用失效时,计数器就减1。任何时刻只要计数器为0则回收。但是这种算法无法解决对象之间互相循环引用的问题。如A引用B,而B又引用A,计数器永远不为0,这两个对象再也无任何引用。这样GC不能回收这两个对象。
因此,在JAVA中,采用了可达性分析算法来解决这个问题,判断对象是否存活。
可达性分析算法:通过GCRoots的对象作为起点,从这些节点向下搜索,搜索走过的路径称之为引用链(Reference Chain),当一个对象到达GCRoots没有任何链相连,则证明此对象不可用,可以被GC回收。

可达性分析算法

上图蓝色部分将会被GC回收。

2.垃圾收集算法

2.1 标记-清除算法

标记-清除算法是最基础的垃圾收集算法。分为标记和清除两个阶段:
首先标记出需要回收的对象,在标记完成后统一回收所有被标记的对象。
存在的问题: 一是效率低,标记和清除两个过程效率都不高。二是空间问题,标记清除后会产生大量的不连续的内存碎片。空间碎片太多会导致程序在运行过程中需要分配较大对象时无法找到连续内存而不得不提前触发GC。

2.2复制算法

为了解决效率问题,复制算法应运而生。它将可用内存分为大小相等的两块,每次只使用其中一块,当其中一块内存耗尽,触发GC时就将还存在的对象复制到另外一块内存上面,然后再把已使用过的内存空间一次性清除。这样实现了对整个半区的GC,内存分配时完全不用考虑碎片的情况。缺点在于这种算法将内存的可用大小缩小了一半。

2.3 标记-整理算法

复制算法当对象存活率较高的情况时,照样会出现效率低下的问题,另外内存要浪费50%。为了避免上述问题,出现了 标记-整理算法。(mark-compact) 其标记过程与标记-清除算法一样,但后续步骤不直接清除,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。

2.4分代收集法

根据对象的存活周期将内存分为几块,如当前hotsport就分为新生代和老年代,然后在各个年代采用不同的收集算法。新生代采用复制算法,老年代采用标记清除或者标记整理算法。

3.垃圾收集器

垃圾收集器是内存回收算法的具体实现。不同的厂商不同版本的虚拟机对垃圾收集器的实现有很大差别。在HotSport虚拟机1.7版本中,所有垃圾收集器如下图所示:

HotSpot虚拟机的垃圾收集器

3.1 Serial收集器

Serial收集器是一个单线程收集器,只会使用一条线程去收集,同时需要暂停其他所有工作线程,直至收集结束。

Serial/Serial Old 收集器运行示意图

优点:
简单高效,在单CPU环境中没有线程开销,可以获得最大的效率。
适用于运行在Client模式下的虚拟机。

3.2 ParNew收集器

ParNew收集器是Serial收集器的多线程版本,除了多线程收集之外,其余包括控制参数、收集算法、对象分配规则、回收策略等都与Serial收集器一样。

ParNew/Serial Old收集器运行示意图

ParNew收集器是jvmServer模式下的首选新生代收集器,除Serial收集器外,只有ParNew收集器能与CMS收集器配合工作。默认开启的收集线程数与CPU的数量相同。可以通过 -XX:parallelGCThreads参数来限制垃圾收集的线程数。

3.3 Parallel Scavenge收集器

Parallel Scavenge收集器是一个新生代收集器,也采用复制算法,并行多线程收集。特点在于达到一个可控目标吞吐量(Throughput)。
吞吐量 = 运行用户代码的时间/(运行用户代码的时间+GC耗时)。
-XX:MaxGCPauseMillis 设置停顿时间。
-XX:GCTimeratio 设置吞吐量。
Parallel Scavenge收集器 能够根据上述两个参数进行自适应调节。

3.4 Serial Old收集器

Serial Old收集器是Serial收集器的老年代版本,同样式一个单线程收集器,使用标记整理算法。收集器的主要意义也是提供给Client模式下使用,在Server模式下,主要有两大用途:

3.5 Parallel Old收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多线程的标记整理算法。
在注重吞吐量以及CPU资源敏感的场合,优先考虑Parallel Scavenge和Parallel Old的组合进行收集。

parallel Scavenge/Parallel Old收集器运行示意图

3.6 CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一种以获得最短回收停顿时间为目标的收集器。主要应用在互联网或BS系统的服务器上,这类应用尤其重视服务器的响应速度,希望停顿时间最短,以给用户最好的体验。
CMS时基于标记清除算法实现的,主要分为4个步骤:
初始标记(CMS initial mark):标记GC Roots能直接关联到的对象,速度很快。
并发标记(CMS concurrent mark):进行roots tracing过程。
重新标记(CMS remark):修正并发标记阶段因用户程序继续运作而导致标记产生变动的哪一部分对象的标记记录,这个极端停顿时间比初始标记长。但远比并发标记短。
并发清除(CMS concurrent sweep):回收资源。
上述步骤中,初始标记、重新标记这两个步骤需要停止所有线程。

CMS收集器运行示意图

CMS收集器缺点:
CMS收集器对CPU资源非常敏感,在CPU资源很匮乏时,效率会非常滴,造成停顿时间过长。
CMS收集器无法处理浮动垃圾,即在CMS收集器收集过程中新产生的垃圾,如果浮动垃圾较大,会导致CMS失败。当CMS失败后,会启动后背预案,临时启用SerialOld收集器来进行老年代收集。这样停顿时间就会比较长。
CMS收集器基于标记清除算法,会产生大量的内存碎片,需要额外开启内存整理。通过参数 -XX:CMSFullGCsBeforeCompation,设置执行多少次不压缩的GC后进行一次压缩。

3.7 G1收集器

G1是一款面向服务端的垃圾收集器,具有如下特点:
并行与并发:G1能充分利用多CPU,多环境下的硬件优势,使用多个CPU来缩短停顿时间,部分其他收集器需要停顿的动作,G1中可以并发的方式进行执行。
分代收集:G1中仍然使用分代收集。
空间整合:G1基于标记整理算法实现收集,局部来看是基于复制算法,运行期间不会产生内存碎片。
可预测停顿:可以指定停顿的时间片段。
G1可分为如下步骤:
初始标记(Initial marking)
并发标记(Concurrent marking)
最终标记(Final Marking)
筛选回收(Live Data Counting and evacuation)

G1收集器运行示意图

4.垃圾回收器参数总结

参数 描述
UserSerialGC 虚拟机在client模式下的默认值,打开此开关后,用于Serial+Serial Old的收集器组合进行内存回收
UserParNewGC 打开此开关 使用ParNew + Serial Old收集器组合进行内存回收
UseConcMarkSweepGC 打开此开关,使用ParNew+CMS+Serial Old收集器组合进行内存回收。Serial Old在CMS收集器出现concurrent Mode Failure 失败后的后备收集器
UseParallelGC 在server模式下的默认值,打开此开关后使用Scavenge+Serial Old收集器组合进行回收
UseParallelOldGC 打开此开关后使用 Parallel Scavenge+Parallel Old收集器组合进行内存回收
SurvivorRatio 新生代中Eden区域与Survivor区域的比值,默认为8,表示Eden:Survivor=8:1
PretenureSizeThreshold 直接晋升到老年代对象的大小,设置这个参数后大于这个参数的对象直接在老年代中分配
MaxTenuringThreshold 晋升老年代对象的年龄,每个对象坚持一次MnorGC年龄就加一,当超过这个参数值就进入老年代
UseAdaptiveSizePolicy 动态调整java堆各个区域的大小以及进入老年代的年龄
HandlePromotionFailure 是否允许分配担保失败,即老年代剩余空间不足以应付新生代整个对象都存活的特殊情况
ParalleGCThreads 设置并行GC时进行内存回收的线程数
GCTimeratio GC时间占总时间比率,默认值为99,允许1%的GC时间。只在Parallel Seavenge收集器时生效
MaxGCPauseMillis 设置GC的最大停顿时间,只在Parallel Seavenge收集器时生效
CMSInitiatingOccupancyFration 设置CMS老年代空间被使用多少后触发GC,默认值为68%,只在CMS收集器时生效
UseCMSCompactAtFullCollection 设置CMS收集器完成垃圾收集后是否需要进行一次碎片整理,只在CMS垃圾收集器时生效
CMSFullGCBeforeCompaction 设置CMS收集器进行若干次垃圾收集后再启动一次内存碎片整理,只在CMS垃圾收集器时生效

5. 内存分配与回收策略

MinorGC:新生代发生的垃圾回收动作,一般速度比较快。
MajorGC/FullGC:发生在老年代的GC,出现MajorGC,经常会伴随一次MinorGC。MajorGC速度一般比MinorGC慢10倍以上。
1.大多数情况下,对象在Eden区中进行分配,当Eden中没有足够的分配空间时,虚拟机将进行一次MinorGC。
2.大对象直接进入老年代,避免触发大量内存复制。
3.长期存活的对象进入老年代。
4.动态对象年龄判定,为了能更好的适应不同的程序的内存状况,虚拟机并不是永远需要要求对象的年龄达到MaxTenuringThreshold才能晋升老年代。如果在Survivor空间中相同年龄对象的大小总和大于Surrvivor空间的一半,则年龄大于等于该年龄的对象就可以直接进入老年代。
5.空间分配担保:在发送MinorGC之前虚拟机会先检查老年代最大可用的连续内存空间是否大于新生代所有对象的总和,如果条件成了,则MinorGC可以确保安全。如果不成立,则会检查是否设置了允许担保失败,如果允许,则会继续检查老年代最大可用连续内存空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行一次MinorGC,如果小于,则要进行一次FullGC。

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

推荐阅读更多精彩内容