Java虚拟机之垃圾回收算法

垃圾收集主要是针对堆和方法区进行。程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后就会消失,因此不需要对这三个区域进行垃圾回收。

判断对象是否存活

主要有引用计数法和可达性分析法,Java使用的是可达性分析法。

1、引用计数法
给对象添加一个引用计数器,每次被引用,计算器加一,引用失效,计算减一。当引用数为0时,表示对象不存活。但无法解决循环引用问题,当两个对象出现循环引用的情况下,此时计数器永远不为0。

2、可达性分析
以GC Roots对象为起点,向下搜索,节点所走的路径成为引用链。当一个对象和引用链没有相连时,表示这个对象不可达。可达的对象都是存活的,不可达的对象可被回收。
其中GC Roots主要包含:

  • 虚拟机栈引用的对象;
  • 本地方法栈引用的对象;
  • 方法区静态属性引用的对象;
  • 方法区常量引用的对象。
    在这里插入图片描述
    但是即使可达性分析判定为不可达对象,但并不是“非死不可”,此时处于缓刑阶段。真正死亡至少经过两次标记(自救):对可达性分析不可达的对象进行第一次标记,并进行筛选。筛选条件是重写finalize() 方法且还没有调用的对象,若通过筛选将其放入队列中,进行第二次标记。在执行finalize()方法时(执行finanize() 方法后可能能让对象重新被引用),该对象依然没有被引用,才会被真正回收掉。finalize方法只能被调用一次。

垃圾回收算法

1、标记-清除算法(mark-sweep):

首先标记出所有需要回收的对象(可达性分析判断是否可以回收),在标记完成后统一回收掉所有被标记的对象;也可以反过来,标记存活的对象,统一清除未被标记的对象。
在这里插入图片描述
在内存中一个“块”的周期为:分块—>存活对象—>垃圾—>分块—>….
所以在清除后,我们会回收对象的这块空间,作为分块,连接到被称为空闲链表的单向链表,后面新建对象需要新分配空间时,只要遍历这个空闲链表就可以找到分块了。

分配时,程序会搜索空闲链表寻找空间大于等于新对象大小 size 的块 block。如果它找到的块等于 size,会直接返回这个分块;如果找到的块大于 size,会将块分割成大小为 size 与 (block - size) 的两部分,返回大小为 size 的分块,并把大小为 (block - size) 的块返回给空闲链表。

不足:

  • 标记和清除过程的效率都随着对象数量增加而降低
  • 会产生大量不连续的内存碎片,导致无法给大对象分配内存。

2、标记-整理(mark-compact):
先标记存活对象,然后让所有存活对象向一端移动,直接清理端边界以外的内存。
在这里插入图片描述
优点:不会产生内存碎片

不足:需要大量移动存活对象,效率比较低。
尤其是老年代这种每次回收都有大量对象存活区域,移动存活对象并更新所有引用极为浪费时间,而且这种移动对象的操作必须暂停全部用户应用程序才能进行。形象称之为“stop the world”。

3、复制算法

将内存分块,每次只使用一块,使用完后,将存活的对象复制到另一块上,商用虚拟机都优先采用这种方法回收新生代,但并不是划分为大小相等的两块,而是一块较大的eden空间和两块较小的survivor空间。eden和survivor大小比例为8:1:1。因为研究表明,新生代中的对象有98%熬不过第一轮收集。

每次使用eden和其中一块survivor,在回收时,将还存活的对象全部复制到另一块survivor上,然后清理eden和使用过的那块survivor。 这样保证了内存利用率达到90%。

但是如果回收的时候有多于10%的对象存活,那么一块survivor就不够用了,此时需要依赖老年代进行空间分配担保,也就是借用老年代的空间存储放不下的对象。

4、分代算法
不同块采用适当的收集算法,一般将堆分为新生代和老年代:

新生代存活率较低:使用复制算法。

老年代存活率比较高,且没有额外空间进行分配担保:使用标记清除或者标记整理算法。

参考:
1、周志明《深入浅出Java虚拟机》
2、https://github.com/CyC2018/CS-Notes

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值