六、垃圾回收算法

一、什么时候垃圾回收

  • GC是有JVM自动完成的,是根据JVM系统环境决定的,时机是不确定的
  • 当然可以手动的调用System.gc()方法进行垃圾回收的,但是这样不推荐,消耗资源。即时这样调用,也只能是通知JVM进行垃圾回收,具体啥时候还要看JVM。
    • Eden区或者S去不够用了,不是满了,是不够用了
    • 老年代不够用了
    • 方法区不够用了
    • System.gc()
  • 已经确定一个对象是垃圾了。那么要怎样才能回收它呢?就要用到垃圾回收算法

二、标记-清除

  1. 先用GC ROOT可达性算法标记出有用对象。
  2. 然后将没用的直接清除
  • 问题:
    • 2次遍历效率低
    • 会造成内存碎片。当下一次分配新的大对象的时候,会因为内存不足导致触发GC
  • 流程图如下在这里插入图片描述
  • 标记-清除算法,衍生出来了对象的分配算法
    • 首次适应算法:就是遍历我们空闲链表,只要找出跟新对象大小一样的空间,然后分配给对象,并且立即返回
    • 最佳适应算法:遍历整个空闲链表,找出跟新对象大小一样的空间,分配给对象,一般都是找到的第一个空间
    • 最差适应算法:遍历整个空闲链表,找出最大的那一块,然后分割给对象。但是这有问题就是造成空间碎片

三、复制

  1. 将内存划分成两块
  2. 先用GC ROOT标记这一块的存活对象,然后复制到另一块里面去。
  3. 将那一块区域整体清掉
  • 问题
    • GC的垃圾收集,其实是一种穷人算法,如果你有钱,内存很大,还GC个菠萝。这种复制算法会浪费内存
    • 所以一般用于小一点的内存,比如说我们的S1和S2区
  • 流程如下
    在这里插入图片描述

四、标记-整理

其实标记整理应该叫做标记-清除-整理,因为它是先标记,在清除,最后整理的

  1. 先用GC ROOT可达性算法标记出有用对象。
  2. 然后将没用的直接清除
  3. 然后整理内存
  • 流程如下
    在这里插入图片描述
  • 双指针整理算法、Lisp2整理算法(滑动整理算法)、单次遍历算法

双指针整理算法

  1. first指针从头开始,second指针从尾开始。
  2. 第一阶段(遍历一次):
    • 当first指针到达空闲内存的时候停住,然后second到达可达性对象的时候停住
    • 将second的可达性对象移动到first的空闲内存哪里
    • 直到两个指针相碰撞
  3. 第二阶段(遍历一次):
    • 将GC ROOT的引用改变为当前移动后的地址。因为第一阶段只是移动了内存中的对象,并没有将GC ROOT上的引用改变
  • 问题:
    • 只能处理对象大小相等的情况
    • 对象在内存中没有“连续性”了,将对象打散到内存里面了。这样会导致,读取的时候要读很多个cache line。
  • 流程图如下在这里插入图片描述

Lisp2整理算法

  1. free指针,scan指针从头开始,end指针永远挂在最后一个位置
  2. 第一阶段(遍历一次):
    • scan指针往前走,当遇到一个可达性对象的时候,看这个可达性对象大小是多少,free就往前走多少
    • 直到scan和end相碰撞,end其实就是用来跟scan做碰撞的
  3. 第二阶段(遍历一次):
    • 将GC ROOT的引用改变成将要移动的地方
  4. 第三阶段(遍历一次):
    • 移动对象到指定的位置
  • 问题:
    • 遍历3次有点慢啊
  • 流程:
    在这里插入图片描述

单次遍历算法

  • 其实就是4.2的Lisp2算法改良
  • 在内存中单独开辟一片空间,去存放对象当前的位置、对象要移动的位置等信息。
  • 第一阶段就是先收集信息,第二阶段拿这个信息直接进行移动。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值