JVM垃圾回收常见算法

一、常用的垃圾回收算法

   引用计数法、标记压缩法、标记清除法、复制算法和分代、分区算法。

1、引用计数法

简单效率低。在堆中每个对象都有一个引用计数器;当对象被引用时,引用计算器加1,当引用被置为空(引用计数器的值为0)或者离开作用域时,引用计数减1,但是不能解决相互引用的问题,所以jvm没有采用这个算法

2、标记压缩法

老年代中大部分对象都是存活对象。它在标记清除算法的基础上做了一些优化。首先 标记所有对象,之后将所有的存活对象压缩到内存的一端。之后清理边界外所有的空间。效果等同于标记清楚算法执行完成后,再进行一次碎片整理。

 

3、标记清除法

垃圾回收分为标记和清除阶段,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象,未被标记的为垃圾对象。在清除阶段,清除未被标记的对象。最大问题是产生空间碎片。

4、复制算法

适用于存活对象少,垃圾对象多的前提下。

将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

把堆分成大小相同的区域,在任何时刻,只有其中的一个区域被使用,直到这个区域的被消耗完成为止,此时垃圾回收器会中断程序执行,通过程序的遍历方式把所有活动的对象复制到另一个区域中,在复制的过程中他们是紧紧挨着布置的,从而可以消除内存碎片。当复制过程结束后程序会接着运行直到这块区域被使用完,然后在采用上面的方法继续进行垃圾回收.

复制算法的代价就是将系统内存折半

JAVA的新生代串行垃圾处理器中,使用了复制算法的思想。

Java 的新生代串行垃圾回收器中使用了复制算法的思想。新生代分为 eden 空间、from 空间、to 空间 3 个部分。其中 from 空间和 to 空间可以视为用于复制的两块大小相同、地位相等,且可进行角色互换的空间块。from 和 to 空间也称为 survivor 空间,即幸存者空间,用于存放未被回收的对象。

在垃圾回收时,eden 空间中的存活对象会被复制到未使用的 survivor 空间中 (假设是 to),正在使用的 survivor 空间 (假设是 from) 中的年轻对象也会被复制到 to 空间中 (大对象,或者老年对象会直接进入老年带,如果 to 空间已满,则对象也会直接进入老年代)。此时,eden 空间和 from 空间中的剩余对象就是垃圾对象,可以直接清空,to 空间则存放此次回收后的存活对象。这种改进的复制算法既保证了空间的连续性,又避免了大量的内存空间浪费。

 

5、分代算法

它将内存区间根据对象的特点分成几块,根据每块内存区间的特点,使用不同的回收算法,以提高垃圾回收的效率。

新生代比较适合使用复制算法。老年代比较适合标记压缩算法或者标记清除算法。

新生代回收的频率很高,但每次回收耗时很短,而老年代回收的频率比较低,但会消耗更多的时间。

为了支持高频率的新生代回收,可能使用了一种叫做卡表的数据结构,卡表为一个比特位的集合,每一个比特位可以用来表示老年代的某一个区域中的所有对象是否持有新生代的对象的引用。这样在新生代GC时,可以不用花费大量时间扫描所有老年代对象,来确定每一个对象的引用关系,而可以先扫描卡表,只有当卡表的标记位为1时,才需要扫描特定区域的老年代对象,而卡表为0,一定不含有新生代的对象引用。在新生代GC时,只需要扫描卡表位为1的老年代空间,找到对应的新生代,打打价款新生代的回收速度。

 

6、分区算法。

分代算法将按照对象的生命周期划分为两个部分,如新生代和老年代。分区算法将整个堆空间花费为连续的不同小区间,每个小区间都是独立的,独立回收。优点是可以控制一次回收多少个小区间。

堆空间越大,一次GC时间越长,从而产生停顿的时间就越长,为了更好控制GC产生停顿的时间,将一块大的内存区域分割成多个小块,根据目标的停顿时间,每次合理地回收若干个小区间,而不是整个堆空间,从而减少GC所产生的停顿。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值