jvm---2、GC收集算法

GC收集器算法:
1、标记--清除算法
2、复制算法
3、标记--整理

4、分代收集算法

写在前面:对象存活算法:
GC 收集器对不再使用(死亡)的对象进行内存回收,那么就要判定一个对象是否存活。
对象存活算法通过对象可达性分析来判定对象是是否存活的。基本思路是:通过一系列称为“GC Roots”对象作为起点,当一个对象到GC Roots 不可达时,证明对象是不可用的(没有外部对象的引用了,如循环引用)。
如下图:A B C D 是可用的, X  Y 虽然相互引用,但是是不可达GC Roots 的所以是不可用的(可以回收的对象)。


GC Root 对象包括下面几种对象:

JVM statck

native

method

statck,

run-time

constant

pool

static

references in method area

Clazz

 

标记--清除算法
算法分为“标记”、“清除”两个阶段,第一个阶段就是标记出“已死亡”对象,第二个阶段把所有已标记的“死亡对象”统一回收。
此算法是最基本的算法,后面的算法都是基于这种思路并对不足的地方进行改进的。
缺点:
1、效率不高

2、标记清除后会产生大量的空间碎片

          

 

复制算法
解决“标记--清除”算法的效率问题。将内存分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活的对象复制到另一块,然后再把不再使用的对象内存一次清理掉。
优点:这样每次都对整个内存的一半区域进行回收,内存分配的时候也不用考虑内存碎片问题,只要移动堆顶指针顺序分配内存就可以,简单高效。
缺点:1、内存只使用了一半,如果不想浪费50%的内存就要有分配担保。2、如果对象存活率高就要进行较多的复制操作

        

现在商业虚拟机都是用“复制算法”来回收新生代的。
新生代分为一个Eden 区和两个 Survivor 区域,每次使用Eden 区和一个 Survivor 区,这样只有一个 Survivor 被浪费。
创建对象时先分配在Eden区,当Eden 区放不下对象时,会产生一次Minor GC,把Eden存活的对象放到 Survivor from 区(如果放不下,把放不下的对象放入old 区),把“死亡对象”清除。再在Eden区分配对象,当下一次Minor GC 时,就会把Eden 区存活对象和Survivor from 区的存活对象一起放到Survivor to 区。再下一次Minor GC时,Survivor to 中对象就放到老年代了(年龄足够)。
如果Survivor 区不够了,就要依赖其它内存块,这时用到老年代进行分配担保(GC收集器执行规则会涉及到)。

 

标记--整理
复制算法不适用对象存活率高的情况,也就是不适用“老年代”。
根据“老年代”对象特点(存活时间比较长,可能几个Full GC 都没有回收),“标记--整理”算法产生。
“标记--整理”算法的标记过程和“标记--清除”算法一样,“标记--整理”是对标存活的记对象的向一端移动,然后直接清理掉边界以外的内存,而“标记--清理”是清理掉“死亡”对象。
这样就不会产生内存碎片。

分代收集算法
当前GC收集都采用“分代收集”算法,就是根据对象的存活周期不同把堆分成几块,一般是把堆分成“新生代”、“老年代”,再根据“新生代”、“老年代”的不同特点分别采用不同的GC收集算法。
“新生代” 存活率代,并且有“老年代”分配担保,所以采用“复制算法”,复制少量的对象就可以快速实现垃圾清理,并且不会产生内存碎片。
“老年代” 存活率高,没有额外的内存进行分配担保,采用“标记--清理”或者“标记--整理”回收内存。

注:具体的算法实现也不是这么绝对,可能是进行几次“标记--清理”后回收后,进行一次“标记--整理”消除内存碎片。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值