前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jvm垃圾回收算法

jvm垃圾回收算法

作者头像
小王不头秃
发布2024-06-19 16:55:37
1510
发布2024-06-19 16:55:37
举报

前言

首先我们需要先搞定几个假说

  • 弱分代假说:绝大多数对象都是朝生夕灭的
  • 强分代假说:熬过越多次垃圾回收的对象就越难以消亡
  • 跨代引用假说:跨代引用对于同代引用来说只占极小数

那么这三个假说有什么用处呢

试想一下,如果有大量的对象都是要被回收的,我们再回收这些垃圾之前是要对所有的内容进行标记,此时,我们是标记那些需要回收的对象,还是标记那些不需回收的对象,这俩者哪个效率较高呢,很明显在以上前提下,标记需要不许回收的更好,这就是弱分代假说的应用

接下来我们来看一下强分代假说,这里我们把对象熬过的垃圾回收的次数成为寿命,那么强分代假说的含义就是对象的寿命越大,越难回收(其实就是可能一直在被使用,不能回收,否则会影响正常的系统运行),此时我们每次扫描还要把所有的对象,包括寿命大的,这就有些浪费时间了,我们大可把寿命超过某个阈值的对象放在一个区域,寿命短的放在一个区域,首先对寿命短的区域进行清理,若清理结束后仍空间不够,这时在对寿命长的区域进行清理,这就大大的节省了时间。寿命长的区域称为老年代,寿命短的称为新生代

跨代引用假说可以这样理解,存在引用关系的对象大都在一种区域(老年代或新生代)中,而那些跨代引用(跨区域引用)的则是极少数。

为什么要区别这个呢

现在我们再做一下假设,假如我们此时需要做新生代回收,但是有可能引用新生代的对象在老年代中,我们又需要再去扫描老年代,那我们设置新生代和老年代的意义在哪,此时只需在新生代上设置一个全局变量Remember set,并且把老年代分为很多小块,只需在Remember set记录哪些老年代块中引用新生代即可,每次新生代回收时只需扫描这些记录的老年代块就可以了。

接下来是关于虚拟机设置的参数

含义

参数

堆初始大小

-Xms

堆最大大小

-Xmx或-XX:MaxHeapSize =size

新生代大小

-Xmn或(-XX:NewSize-size + -XX:MaxNewSize-size )

幸存区比例(动态)

-XX:InitialSurvivorRatio-ratio和-XX:+UseAdaptiveSizePolicy

幸存区比例(ratio是指伊甸园所在比例)

-XX:SurvivorRatio= ratio

晋升阈值

-XX:MaxTenuringThreshold=threshold

晋升详情

-XX:+PrintTenuringDistribution

GC详情

-XX:+PrintGCDetails -verbose:ge

FullGC前MinorGC

-XX:+ScavengeBeforeFullGC

幸存区比例不会变化的垃圾回收器

-XX: +UseSerialGC

串行垃圾回收器(新生代是复制算法,老年是标记整理算法)

-XX:+UseSerialGC= Serial + Serialold

上了解了上述内容之后,我们来了解一下垃圾回收的几种算法

垃圾回收算法

标记-清除

思想

这个咱们可以按照名字来理解了,整个算法分为两个阶段,分别是标记和清除。

  • 标记阶段,咱么在上面已经介绍过了,就是标记需要回收的资源或则不需要回收的资源。
  • 清除阶段,就是回收刚刚标记的对象或未被标记的对象,具体怎么回收就取决于你选择的算法了。
优缺点

该算法是很多算法的基础,但也有几个缺点

  • 算法不稳定,若是采用标记需回收的对象,这时恰恰又有很多对象需要回收,这就造成了回收时间过长
  • 其次,该算法只做清理,而不做整理空间,此时就导致了可能会产生空间碎片,使得虽然剩余空间总大小足够分配给一个对象,但是因为没有连续空间,就导致了无法分配空间问题。

标记-复制

思想

这种算法也是再上述弱分代假说上设置的,也就是说,我们认为大多数对象都是朝生夕灭的,事实确实如此。

首先我们需要将内存分为两块区域,分别称为fromto,当from中满了时,我们就需要对from进行垃圾回收。

先对from中的对象进行标记,而后将那些不需回收的对象复制到to中,然后对from中对象直接清空即可,随后交换from和to的,也就是说现在from就是to,而to就是from。

优缺点
  • 该算法不会产生碎片空间,因为在复制时,我们可以通过调节指针的方式,使得复制过去的对象都可以紧凑的存放在一起。
  • 虽然实现简单,运行起来也很高效,但该算法有一个明显的缺点,这种将空间划分为俩部分的方式,已经浪费了一半空间

目前这种算法被应用到很多虚拟机,如下图,就是一种应用该算法的空间的划分

可以看出,这里内存被分成了老年代与新生代,为什么要设置老年代呢,这是因为我们之前介绍的强分代假说

这里看下新生代,我们可以发现内存分为了伊甸园幸存区俩部分,幸存区又被分为了两部分,可以认为我们上诉提到的from和to。这里一旦伊甸园存满了,就需要进行清理,我们称之为Minor GC,清理过程就是上诉的标记-复制过程,而后我们将伊甸园中幸存的对象移入到幸存区中,然后直接清理伊甸园即可。

在之后伊甸园又满了,我们这时不仅仅要对伊甸园对象进行处理,也要对幸存区中存有数据的那一块进行处理,将二者之中幸存的对象移入到幸存区的另一块中,然后交换二者的角色(即交换from与to的角色)。

如果说清理新生代对象之后仍无法满足对象存储的需求,就需要对老年代中的对象进行回收,此时就发生了Full GC,这里是会对新生代和老年代一起回收,如果还是不可以,这就发生了内存空间溢出的问题。上述这种思想也就是分代回收。即先回收新生代,若是回收结束之后仍内存不足,在进行回收全部的空间。

标记-整理

思想
  • 判断哪些对象未被不可回收的对象直接或间接引用,对其进行标记
  • 清楚时,将可用的对象向前移动,从而使得内存空间更见紧凑,从而实现空间更加连续
优缺点
  • 没有内存碎片
  • 耗费时间较多,例如如果有引用对象引用就是将移动的对象,需要修改大量内容,造成浪费时间,这也是标记整理与标记清除区别
  • 因为要移动对象,这个时间段这些对象的地址可能会发生变化,原本需要使用他们的线程就需要暂停,待将这些线程的使用的引用更新之后才可以继续运行,也就是在垃圾回收这段时间,所有的用户线程都要暂停,也被称为stop the world

总结

在看完上述的分代回收之后,大家可能有疑惑,如果幸存区不够存放幸存对象怎么办,这时候就会出现新生代回收的对象直接晋升至老年代,而不需要进行我们上述提到的达到一定寿命之后才可以晋升。

看起来是没有任何问题的,但可以设想一下,通过上诉这种机制我们可以了解到,老年代的回收频率一定是小于新生代的回收频率,幸存对象直接上升至老年区,导致该对象可能已经该回收了,却一直因为未进行老年代回收而一直迟迟占着空间。

同时我们也可以注意到由于整理空间时会引起stop the world,但不整理又会存在空间碎片,现在有一种折中的方法就是空间足够时使用标记清理,当空间碎片太多时,就是用标记整理进行一下整理即可

该博客仅仅是我自己在学习之后的总结,有什么问题,还请大佬们指教。还有分区的方式进行整理等以后博客再整理,就到这了

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 垃圾回收算法
    • 标记-清除
      • 思想
      • 优缺点
    • 标记-复制
      • 思想
      • 优缺点
    • 标记-整理
      • 思想
      • 优缺点
  • 总结
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档