JVM垃圾回收机制

JVM垃圾回收机制

以对象为单位来进行回收

如何确定该对象是垃圾

Java 中使用 可达性分析方法

Python 中时使用 引用计数方法

引用计数

使用额外的计数器,来记录某个对象有多少个引用指向它(如果没有引用指向它了,它就相当于垃圾了)

  1. 在多线程的情况下,可能存在多个线程修改同一个变量的情况

  2. 如果当前类的大小比较大时,多一个引用计数没啥;但如果但钱类很小,在引入一个变量来计数,就会有很大的空间开销

  3. 存在循环引用的问题

    image-20230325124502787

可达性分析

以代码中的一些特殊的变量作为起点,然后以起点触发,看看哪些对象都能被访问到,只要对象能被访问到,就被标记为可达【借助二叉树:如果是节点就可到达,如果连接节点的线断了,就相当于不可达了】,当完成一圈标记后,剩下没有标记的就是不可达,就是垃圾

起点称为GCRoot

  1. 局部变量表中的引用【局部变量】,所有的局部变量都可以视为是 GCRoot
  2. 常量池中对应的对象
  3. 方法区中,静态引用类型的成员

如何释放对象

常用策略

标记-清除

先通过可达性分析,找到垃圾,然后释放【确实把内存释放了,但是出现了很多内存碎片;因为 new 对象分配的空间都是需要连续的】

复制

为了解决上述中的内存碎片问题,引入了复制算法

将空间一分为二,每次只用一半空间,但进行可达性分析后,将可达的数据进行复制到另一半空间中,然后整体释放之前占用的一半空间,就达到了空间连续

问题:直接相当于少了一半空间

标记-整理

类似于顺序表删除元素【耗时】

分代回收

将上述的算法进行综合使用,扬长避短

给对象引入了一个概念,年龄,这里的年龄指的是对象活过 GC 的轮次;对象刚创建出啦,未被 GC 洗礼过,年龄就是0,洗礼过一次就 + 1,根据年龄不同,被分为新生代和老年代

image-20230325132712703

  1. 新创建的对象都放在伊甸区中
  2. 伊甸区中的对象绝大部分都活不过一轮GC,活过一轮 GC 的就放到幸存区【幸存区中的对象不会很多,所以不需要很大的空间】,从伊甸区到幸存区就是采用复制算法
  3. 幸存区的对象又会经过一轮又一轮的 GC 洗礼,每次都会淘汰一部分,未被淘汰的对象就被放入另一个幸存区中【复制算法】
  4. 当在幸存区中,很多轮的 GC 洗礼后,对象依旧存在,就将其复制到老年代中
  5. 对象在老年代中,依然要经历 GC 洗礼,但是周期性就可以缩短了【这就可以采用 标记-整理算法了,因为回收的次数减少了】

特例

如果当前的对象占用空间特别大,就直接将其放入老年代【大对象在复制算法中,不怎么友好】

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值