垃圾回收算法

  • 标记 - 清除算法
  • 复制算法
  • 标记 - 整理算法
  • 分代收集算法

1 标记 - 清除算法

实现原理

  • 标记出所有需要回收的对象。
  • 统一回收所有被标记的对象。

特点

  • 标记和清除效率不高。
  • 产生大量不连续的内存碎片。
  • 标记清除算法是最基础的收集算法,后面的几种算法都是基于这种思路并对其不足进行改进而得到的。 算法分为“标记”和“清除”两个阶段。
  • 标记 : 首先标记处所有需要回收的对象,在标记完成后统一回收所有被标记的对象。标记的判定就是通过可达性分析算法分析出可回收对象。
  • 清除 : 标记完成后会回收对象。但是这其中存在着两个不足问题 : 第一是标记和清除这两个过程效率不高。其次是清除之后会产生大量不连续的内存碎片。
  • 清除 : 标记完成后会回收对象。
  • 但是这其中存在着两个不足问题 : 第一是标记和清除这两个过程效率不高。其次是清除之后会产生大量不连续的内存碎片。
  • 空间碎片太多可能会导致以后在程序运行过程中需要分配比较大对象时,无法找到足够连续内存。从而提前触发依次GC。
160f7b667fa1cd3b.png
  • 相当于生活中标记不需要的物品,然后找几个人把这些东西丢了。 但是由于房间的空间是有限的,如果一直没有整理房间,如果有大件家具搬进来时,没有足够的空间可能要再标记清除一下不需要的物品,如果还是没有办法放下这件大家具,抛出OOM异常。丢(Out)到(Of)门外(Memory)。

2 复制算法

实现原理

  • 将内存划分为大小相等的两块。
  • 一块内存用完之后复制存活对象至另一块。
  • 清理另一块内存。

特点

  • 实现简单,运行高效。
  • 浪费一半空间,代价大。
  • 为了解决效率问题,复制收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
  • 当这一块的内存用完了,就将还存活的对象复制到另一块上面,然后把已使用过的那一块内存空间全部清理。
  • 这样便不用考虑内存碎片问题,只要移动堆顶指针,重新按顺序分配内存即可,实现简单,运行高效。
  • 只是这种算法的代价是将活动使用的内存缩小为原来的一半。
160f7b667fa1cd3b.png
  • 复制算法当存活对象越少(或者垃圾很容易产生)时,它的效率越高。
    也就是你只要将一些少量需要用到的对象丢到另一片干净的内存中,就可以轻松的大扫除。

换句话说,如果你需要保留的对象很多,那么便需要又费力又频繁的搬动到另一块内存中。

  • 复制收集算法在对象存活率较高时就要进行较多的操作,效率就会变得很低。并且只能使用50%的空间。

3 标记 - 整理算法

实现原理

  • 标记过程与 ”标记-清除“ 算法一样。
  • 存活对象往一端进行移动。
  • 清理其余内存。

特点

  • 避免 ”标记-清除” 算法导致的内存碎片。
  • 避免复制算法的空间浪费。
  • 标记 : 因为存活的对象比较多,我们将这些对象标记起来。然后接下来整理到一块。
  • 整理 : 让所有标记过的对象都向一端移动,然后直接清理掉端边界以外的内存。(按内存地址一次排列)
160f7b66a84fa47a.png

4 分代收集算法

特点

  • 结合多种收集算法的优势。
  • 新生代对象存活率低 => “复制” 算法(注意这里每一次的复制比例都是可以调整的,如一次仅复制 30% 的存活对象)。
  • 老年代对象存活率高 => “标记-整理” 算法。

当前很多商业虚拟机都采用分代收集(Generational Collection)算法作为垃圾收集器。

  • 这种算法只是根据对象存活周期的不同将内存划分为几块,进而采用不同的回收算法的策略。
  • 一般是把Java堆分成新生代和老年代。
  • 新生代 : 对象朝生暮死,存活的对象少,可回收对象多。
    选用复制算法,只要付出少量存活对象的复制成本就可以完成收集。
  • 老年代 : 对象存活率高,回收的对象很少。
    选用标记 - 清理算法,或者标记 - 整理算法来进行回收。
  • 对于新生代采取复制算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,采用复制算法效率最高。
  • 但实际中并不是按照上面算法中说的1:1的比例来划分新生代的空间的,而是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,比例为8:1:1(比例可以调整)。
  • 每次使用Eden和其中一块Survivor,当回收时,将Eden和刚才用过的Survivor空间中还存活的对象一次性的复制到另一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。(后面会继续研究,如果这次复制的对象大小超过Survivor空间,将会有分配担保机制。)
  • 由于老年代的特点是每次回收都只回收少量对象,使用的是标记 - 清理算法,或者标记 - 整理算法来进行回收。它与新生代的比例为 2(老年代) : 1(新生代)。当然这个比例也是可以调整的。
160f7b66a6600310.png

分代收集算法工作流程

  • 1 . 分配了一个又一个对象 : 放到Eden区。
  • 2 . 不好,Eden区满了,只能GC(新生代GC:Minor GC)了 : 把Eden区的存活对象copy到Survivor A区,然后清空Eden区(本来Survivor B区也需要清空的,不过本来就是空的)
  • 3 . 又分配了一个又一个对象 : 放到Eden区。
  • 4 . 不好,Eden区满了,只能GC(新生代GC:Minor GC)了 : 把Eden区和Survivor A区的存活对象copy到Survivor B区,然后清空Eden区和Survivor A区。
  • 5 . 又分配了一个又一个对象 : 放到Eden区。
  • 6 . 不好,Eden区满了,只能GC(新生代GC:Minor GC)了 : 把Eden区和Survivor B区的存活对象copy到Survivor A区,然后清空Eden区和Survivor B区
    为什么不是一块Survivor空间而是两块?
  • 这里涉及到一个新生代和老年代的存活周期的问题,比如一个对象在新生代经历15次(仅供参考)GC,就可以移到老年代了。问题来了,当我们第一次GC的时候,我们可以把Eden区的存活对象放到Survivor A空间,但是第二次GC的时候,Survivor A空间的存活对象也需要再次用Copying算法,放到Survivor B空间上,而把刚刚的Survivor A空间和Eden空间清除。第三次GC时,又把Survivor B空间的存活对象复制到Survivor A空间,如此反复。 所以,这里就需要两块Survivor空间来回倒腾。

为什么Eden空间这么大而Survivor空间要分的少一点?

  • 新创建的对象都是放在Eden空间,这是很频繁的,尤其是大量的局部变量产生的临时对象,这些对象绝大部分都应该马上被回收,能存活下来被转移到survivor空间的往往不多。所以,设置较大的Eden空间和较小的Survivor空间是合理的,大大提高了内存的使用率,缓解了Copying算法的缺点。
    我看8:1:1就挺好的,当然这个比例是可以调整的,包括上面的新生代和老年代的1:2的比例也是可以调整的。
    新的问题又来了,从Eden空间往Survivor空间转移的时候Survivor空间不够了怎么办?直接放到老年代去。

参考

Java垃圾回收(一)—— 回收机制

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

推荐阅读更多精彩内容