Java垃圾回收算法

Java垃圾回收(Garbage Collection,GC)

怎样定义垃圾

引用计数算法:在对象头中分配一个空间来保存该对象被引用的次数(Reference Count),当引用计数为0时回收该对象。
缺点:当存在两个对象A,B,分别由a, b来引用,即a = A, b = B,假设A中的字段与B中的字段存在相互引用,当将a,b设置为null时,并不能让垃圾回收器回收A,B这两个对象(其对象内部相互循环引用),此时造成了内存泄漏,代码如下:

public class ReferenceCountingGC{
    public Object instance;
    public static void main(String[] args){
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        objA.instance = objB;
        objB.instance = objA;
        objA = null;
        objB = null
    }
}

可达性分析算法:通过一些被称为引用链(GC Roots)的对象作为起点,树结构,向下搜索,能到达的对象都是存在引用,而不能到达的对象(属于另外一个树了)是没有引用的,即使它们之间相互引用。

在这里插入图片描述
可作为GC Root的对象:

  • 虚拟机栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象在
  • 本地方法栈JNI(Native方法)引用的对象

无论是引用计数法还是可达性分析法,都与对象的引用有关。Java将引用分为四类:

  • 强引用
  • 软引用
  • 弱引用
  • 虚引用

方法区的垃圾回收:主要回收废弃常量和无用的类

  • 判断一个常量是否为废弃常量:假如一个常量没有被任何对象引用,那么将该常量定义为废弃常量
  • 判断一个类是否为无用的类:
    • 该类的所有实例都已经被回收,即Java堆中不存在该类的任何实例
    • 加载该类的ClassLoader已经被回收
    • 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
垃圾回收算法

在确定内存中哪些是垃圾后,再看怎样将垃圾清理掉:
1 标记-清除算法(Mark-Sweep)
将内存中的垃圾标记出来,然后统一清除。

缺点:

  • 效率不高
  • 产生内存碎片

2 复制算法
将内存平分为大小相等的两块,每次只使用其中一块,当这一块内存不足时,将还存活的对象复制到另一块,然后统一对前一块的内存进行一次性清除。相当于建了100平的房子,每次只住50平,代价太大!!!
3 标记整理算法
标记,但不清理,而是将后面存活的对象往前面移动,解决了内存碎片问题,也没有复制算法只用一半空间的弊端,但是内存变动频繁导致效率很低!
4 分代收集算法(Generational Collection)
融合前3种算法,根据对象存活周期不同将内存划分为几块,将java堆分为新生代和老年代,新生代中每次都有大量的对象死去,只有少量的对象存活,这时使用复制算法,只需要复制少量的对象就可以完成手机。而老年代的对象存活率高,适合使用标记清除算法或标记整理算法来回收

内存模型
Java堆是JVM管理的最大一块内存,而堆是垃圾回收器管理的主要区域。将堆分为两个区域,年轻代(1/3)和老年代(2/3)。
年轻代又分为Eden和Survior区(8:1:1)
新生对象大多在Eden分配,当Eden区没有足够空间时,虚拟机发起一次Minor GC
Survivor区相当于Eden区和Old区的缓冲区,类似于交通中的黄灯。其中包括From区和To区,每次执行Minor GC会将Eden和From中存活的对象放到To区,如果To放不下了,就直接进入Old区

为啥需要Survivor?如果没有Survivor,每次执行Minor GC都会将存活对象塞进Old区,导致Old区很快就被塞满。而很多对象虽然第一次GC时没有死亡,第二,第三次后可能就死亡了,所以第一次就移入Old区不是明确的选择

为啥需要两个?From和To
假如只有一个,每次从Eden区加入Survivor区的对象都可能在下一次GC时死亡,这时利用标记清除算法会导致Survivor区产生大量的内存碎片,很快就导致Survivor无法被使用。而使用两个区,From和To,可以巧妙地使用标记复制算法,解决内存碎片问题,From和To交替交换职责,每次让一个区有对象,另一个区为空,下次有对象的区将对象移入Old区,无对象的区从Eden区接收对象

Old区
Old区只有在Major GC时才清理,每次GC都会触发“Stop-The-World”,此处使用的是标记整理算法

一些对象在创建时会直接进入Old区:
1 大对象
避免在Eden区及2个Survivor区发生大量复制
2 长期存活对象
3 动态对象年龄

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值