JVM垃圾回收算法

垃圾回收步骤:判断对象是否存活 - 缓刑阶段 - 垃圾回收

一、判断对象是否存活

1、引用计数法

算法思想:给每个对象加引用计数器,每当引用该对象时,引用计数器+1;不再引用时(引用失效),引用计数器-1;任意时刻,当计数器值为0时,表示对象不再存活

优点:实现简单、判断效率较高

缺点:无法解决循环引用问题

2、可达性分析算法(JVM采用此算法)

算法思想:通过一系列称为"GC Roots"的对象开始向下寻找,如果从"GC Roots"到这个对象有路(引用链)可走(可达),认为这个对象存活;否则,该对象不再存活

注:可以作为"GC Roots"的对象:

I.本地方法栈、虚拟机栈中引用的对象(局部变量)

II.类中的常量与静态变量引用的对象(成员变量不可)

Java中的四种引用类型

a.强引用(Strong Reference)

Object obj = new Object();

obj 是一个强引用,强引用在代码中普遍存在。只要对象被任意一个强引用指向,无论是否发生内存溢出(OOM),都不能回收此类对象。所以在不使用此类对象时即使释放,便于系统回收

b.软引用(Soft Reference):JDK1.2之后提供SoftReference类描述软引用

SoftReference<Integer> sr = new SoftReference<>(1);

sr 是一个软引用,用来描述一些有用但不必须对象(如缓存对象)。对于仅被软引用指向的对象,在系统将要发生内存溢出之前,会将所有软引用对象进行垃圾回收。若内存够用,这些内存仍然保留。

c.弱引用(Weak Reference):JDK1.2之后使用Weak Reference类描述弱引用

WeakReference<Integer> wr = new WeakReference<>(1);

wr 是一个弱引用,仅被弱引用指向的对象最多只能生存到下一次GC开始之前。当垃圾回收器开始工作时,无论当前内存是否够用,都会回收掉仅被弱引用关联的对象。

d.虚引用(Phantom Reference):JDK1.2之后提供PhantomReference类描述虚引用

ReferenceQueue<Integer> rq = new ReferenceQueue<>();
PhantomReference<Integer> pr = new PhantomReference<>(1,rq);

pr 是一个虚引用,虚引用也称为幽灵引用或幻影引用,是最弱的一种引用关系。虚引用不会对生命周期产生任意影响,也无法通过虚引用取得一个对象。为一个对象设置虚引用的唯一目的就是在这个对象被GC之前,收到一个系统通知。

二、对象的缓刑阶段 

protected void finalize() throws Throwable{}

当一个对象被标记为不可达时,所有不可达对象处于"缓刑"阶段,GC线程在回收时,

I.若此对象所在的类没有覆写finalize(),系统认为此对象不再存活,可回收

II.若此对象所在的类覆写finalize()

a.未被JVM调用,则由JVM调用finalize(),若此对象再次与"GC Roots"有了关联,那么对象就存活;否则,对象不再存活

b.已被JVM调用,系统认为此对象不再存活,可回收

三、GC算法

1、标记-清除算法

算法思想:分为"标记"和"清除"两个阶段;首先标记出所有需要回收的对象,在标记完成后统一回收被标记的对象

缺点:

a.效率问题:标记和清除过程的效率都较低

b.空间问题:标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致之后在程序运行中需要分配较大对象时,无法找到足够大的连续内存而不得不提前触发另一次垃圾回收

2、复制算法

算法思想:将内存按容量划分为大小相等的两块,每次只使用其中的一块。当已使用的内存区域需要进行垃圾回收时,会将该区域存活的对象复制到未使用的内存区域上面,然后一次清理已使用的内存区域。

优点:对整个半区进行垃圾回收,内存分配时不需要考虑空间碎片等问题,只需移动堆顶指针,按顺序分配即可

3、标记-整理算法

算法思想:首先标记所有需要回收的对象,标记完成后将存活的对象都向一端移动,然后直接清理掉端边界以外的内存

4、分代收集算法

I.新生代:对象存活率非常低,采用复制算法

将新生代分为一块较大的Eden区和两块较小的Survivor区(From区和To区),每次使用Eden区和其中一块Survivor区。当Survivor空间不足时,需要依赖其他内存(老年代)进行分配担保

Eden:Survivor From:Survivor To = 8:1:1,每次新生代可用内存空间为整个新生代容量的90%,剩下的10%用来存放回收后存活的对象

复制算法具体流程

a.当Eden区第一次满时,触发第一次GC,将Eden区存活的对象复制到Survivor From区;清空Eden区

b.当Eden区第二次满时,触发第二次GC,将Eden区与Survivor From区存活的对象复制到Survivor To区;清空Eden区和From区

c.当Eden区第三次满时,触发第三次GC,将Eden区与Survivor To区存活的对象复制到Survivor From区;清空Eden区和To区

部分对象会在From与To区来回复制,交换15次(默认),若对象仍然存活,就会将该对象移动到老年代

特殊情况:如果存活对象占用内存过大(From区与To区容纳不下),直接将该对象移动到老年代

II.老年代:对象存活率较高,没有额外空间对其进行分配担保,采用标记-整理算法

注意: 

MinorGC:发生在新生代的垃圾回收,采用复制算法,效率较高,发生频率较高

FullGC(MajorGC):发生在老年代的垃圾回收,采用标记-整理算法,速度一般比MinorGC慢10倍以上,发生效率较低。一般发生FullGC至少会伴随一次MinorGC(并非绝对)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值