jvm 垃圾收集算法

经过上篇如何判断对象是否死亡,那么jvm要对死亡的对象进行垃圾回收,垃圾回收的算法主要有以下几种:

一、标记-清楚算法

该算法分为“标记”和“清除”阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。它是最基础的收集算法,后续的算法都是对其不足进行改进得到。这种垃圾收集算法会带来两个明显的问题:

  • 一个是效率问题,标记和清除两个过程的效率都不高
  • 一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作

黑色代表要回收的对象,灰色代表不用回收的对象,白色代表空闲的内存。

二、复制算法

为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。

这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。

现在的商业虚拟机都采用这种收集算法来回收新生代,研究表明,新生代中的对象 98%是“朝生夕死”的,所以并不需要按照 1:1 的比例来划分内存空间,而是将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 和其中一块 Survivor。 Survivor from 和Survivor to ,内存比例 8:1:1

当回收时,将 Eden 和 Survivor 中还存活着的对象一次性地复制到另外一块 Survivor 空间上,最后清理掉 Eden 和刚才用过的 Survivor 空间。HotSpot 虚拟机默认 Eden 和 Survivor 的大小比例是 8:1, 也就是每次新生代中可用内存空间为整个新生代容量的 90% (80%+10%),只有 10% 的内存会被“浪费”。当然,98%的对象可回收只是一般场景下的数据,我们没有办法保证每次回收都只有不多于 10%的对象存活,当 Survivor 空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保(Handle Promotion)。

三、标记-整理算法

根据老年代的特点提出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。

标记整理算法解决了什么问题

复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。更关键的是,如果不想浪费 50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都 100%存活的极端情况,所以在老年代一般不能直接选用这种算法

四、分代收集算法

当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。

原文地址:https://www.cnblogs.com/woxbwo/p/11575932.html

时间: 2024-10-07 22:23:51

jvm 垃圾收集算法的相关文章

JVM垃圾收集算法(标记-清除、复制、标记-整理)

 [JVM垃圾收集算法] 1)标记-清除算法: 标记阶段:先通过根节点,标记所有从根节点开始的对象,未被标记的为垃圾对象(错了吧?) 清除阶段:清除所有未被标记的对象 2)复制算法: 将原有的内存空间分为两块,每次只使用一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未被使用的内存块中,然后清除正在使用的内存块中的所有对象. 3)标记-整理算法: 标记阶段:先通过根节点,标记所有从根节点开始的可达对象,未被标记的为垃圾对象 整理阶段:将所有的存活对象压缩到内存的一段,之后清理边界所有的空间

java比c++强大之处jvm垃圾收集算法

java可以自动进行垃圾收集,c++需要手动释放内存,这个功能将程序员解放出来,能将更多的注意力放在需要实现的业务上,这也是java相对c++的一个巨大优势,jvm有哪些垃圾收集算法呢? 标记清除算法:算法分为标记和清除两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象 从图中可以看出这种算法的缺点在于,垃圾被回收以后造成了大量不连续的内存碎片.碎片太多可能会导致以后需要分配较大对象时,无法找到连续的足够内存从而频繁触发垃圾收集,降低系统效率. 复制算法:为了解决"标记

【004】【JVM——垃圾收集算法】

 垃圾收集算法 垃圾收集算法的实现涉及大量的程序细节,而且各个平台的虚拟机操作内存的方法又各不相同,介绍几种垃圾收集算法的思想及其发展过程. 标记-清除算法 垃圾收集分为"标记"和"清除"两个阶段:首先标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象.说它是最基础的收集算法,其他收集算法都是基于这种思路并对其不足进行改进而得到的.它的主要不足有两个: 效率问题,标记和消除两个过程的效率都不高: 空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎

JVM——垃圾收集算法

标记-清除算法 复制算法 标记-整理算法 分代收集算法 1.标记-清除算法 最基础的收集算法,如其名,算法为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. 两个不足: 1)效率问题,标记和清除两个过程的效率多不高: 2)空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作. 2.复制算法 这种算法是为了解决效率的问题.它将可用内存按

Jvm垃圾收集算法

标记-清除 标记-清除算法是现代垃圾回收算法的思想基础.标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段.一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象.因此,未被标记的对象就是未被引用的垃圾对象.然后,在清除阶段,清除所有未被标记的对象 标记-整理 根据老年代的特点提出标记-整理算法.它在标记-清除算法的基础上做了一些优化.和标记-清除算法一样,标记-整理算法也首先需要从根节点开始,对所有可达对象做一次标记.但之后,它并不简单的清理未标记的对象,而是将所有

JVM垃圾收集算法的选择

1. 介绍 JVM提供了多种垃圾收集器,应该根据应用选择一种合适的垃圾收集器. 垃圾回收管理内存通过如下操作: 在年轻代分配对象,把年龄大的对象晋升到老年代. 当年老代超过阈值的时候,并发标记收集. 通过合并内存,拷贝内存的方式对内存进行整理,回收可以内存. 垃圾回收什么时候会产生问题?对于有些应用,垃圾回收永远都不会成为问题,有些应用在垃圾回收期间短暂的暂 停,适当的垃圾回收频率下也可以表现的很好. 阿姆达尔定律(http://ifeve.com/amdahls-law/)意味着程序的性能受限

JVM垃圾回收2(垃圾收集算法)

根据<深入理解java虚拟机>这本书总结 一.关于几个概念:(标记垃圾算法.垃圾收集算法.垃圾收集器) 前面说了如何寻找jvm垃圾,有两种方法:引用计数法/可达性算法.这篇准备讲,标记完垃圾之后,回收的算法,这里的算法只是垃圾回收的思想.后面会讲到多种垃圾收集器,这里的垃圾收集器就是运用了垃圾手机算法的思想,可以说是具体实现. 这里还是想多余的说一下这三个概念: 垃圾标记算法:标记垃圾的方法 垃圾收集算法:一种回收思想,供垃圾收集器使用.可能用在年轻代,也可能用在老年代(当然现在来说老年代和年

JVM(五)-垃圾收集算法和垃圾收集器

一.垃圾收集算法 (1)标记-清除算法 "标记-清除"(Mark-Sweep)算法,如它的名字一样,算法分为"标记"和"清除"两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象.之所以说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其缺点进行改进而得到的. 它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高:另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,

【深入理解JVM】:垃圾收集算法

垃圾收集算法主要有以下几种:标记-清除算法(mark-sweep).复制算法(copying)和标记-整理算法(mark-compact). 标记-清除算法 算法的执行过程与名字一样,先标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象.该算法有两个问题: 标记和清除过程效率不高.主要由于垃圾收集器需要从GC Roots根对象中遍历所有可达的对象,并给这些对象加上一个标记,表明此对象在清除的时候被跳过,然后在清除阶段,垃圾收集器会从Java堆中从头到尾进行遍历,如果有对象没有被打上标记