浅谈一下JVM垃圾回收算法

 更新时间:2023年04月27日 09:26:38   作者:索码理  
这篇文章主要介绍了一下JVM垃圾回收算法,Java有着自己一套的内存管理机制,不需要开发者去手动释放内存,开发者只需要写好代码即可,运行过程中产生的垃圾都由JVM回收,需要的朋友可以参考下

Java有着自己一套的内存管理机制,不需要开发者去手动释放内存,开发者只需要写好代码即可,运行过程中产生的垃圾都由JVM回收。那JVM都是用哪些算法进行垃圾回收呢?

标记-清除(Mark-Sweep)算法

标记-清除(Mark-Sweep)算法是最早出现也是最基础的垃圾收集算法。顾名思义,标记-清除算法分为两个阶段:

  • 标记:标记出所有需要回收的对象
  • 清除:清除掉所有被标记的对象

标记-清除前后

优点:

  • 简单,容易理解
  • 垃圾少时,效率高

缺点:

  • 会产生内存空间碎片,内存空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作
  • 性能不稳定,如果内存中大部分都是要回收的垃圾对象,标记和清除效率会随着垃圾的数量而降低

复制(Copying)算法

为了解决标记-清除算法面对大量可回收对象时执行效率低的问题,于是有了复制(Copying)算法。复制算法是将内存一分为二,当一块内存使用完成之后,会将存活的对象移动到另一块预留未使用的内存空间,然后将使用过的那块内存空间清理掉。

复制前后

优点:

  • 实现简单,运行高效
  • 不会产生内存空间碎片

缺点:

  • 因为要预留一半内存空间,所以内存空间浪费严重
  • 如果内存中多数对象都是存活的,这种算法将会产生大量的内存间复制的开销

Appel 式回收

在1989年,Andrew Appel针对具备“朝生夕灭”特点的对象,提出了一种更优化的半区复制分代策略,现在称为“Appel式回收”。具体做法是分配一块较大的Eden区和两块较小的Survivor区(可以叫做From区和To区,也可以叫做Survivor1区和Survivor2区)。

Img

研究表明,新生代中的对象98%是“朝生夕死”的,所以并不需要按照1:1的比例来划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块 Survivor空间。当回收时,将Eden和Survivor中还存活着的对象一次性地复制到另外一块Survivor空间上,最后清理掉Eden和已经用过的Survivor空间。也就是说,浪费的空间只有一个Survivor空间。

HotSpot虚拟机新生代比例Eden和Survivor空间比例为8:1:1,在使用的时候只使用Eden区和一个Survivor区,也就是说,新生代有90%的空间是在使用的,只有10%的空间是浪费的。新生代中98%的对象可被回收仅仅是“普通场景”下测得的数据,任何人都没有办法百分百保证每次回收都只有不多于10%的对象存活,因此,在Survivor空间不足的情况下,就需要依赖其他内存进行分配担保(Handle Promotion),一般是老年代。就是说如果Survivor空间不足,对象就需要以分配担保的形式进入老年代。

标记-整理(Mark-Compact)算法

标记-整理算法首先标记出所有需要回收的对象,在标记完成后,后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

标记-整理前后

优点:

  • 不会产生内存空间碎片
  • 相较于复制算法,不会有多余空间浪费

缺点:

  • 需要移动对象,效率低。对象移动不单单会加重系统负担,同时需要全程暂停用户线程才能进行,也就是常说的“Stop The World”,同时所有引用对象的地方都需要更新。

标记整理与标记清除算法的区别主要也在于对象的移动。

总结

垃圾回收算法没有好坏之分,只是应用场景不同。老年代存活对象比较多,所以一般采用标记-清除和标记-整理算法,相反,新生代存活对象比较少,所以一般采用复制算法。根据不同的区域的特征采用不同的算法,这就是分代收集理论。

到此这篇关于浅谈一下JVM垃圾回收算法的文章就介绍到这了,更多相关JVM垃圾回收算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java zxing生成条形码和二维吗代码实例

    Java zxing生成条形码和二维吗代码实例

    这篇文章主要介绍了java zxing生成条形码和二维吗代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • spring整合redis以及使用RedisTemplate的方法

    spring整合redis以及使用RedisTemplate的方法

    本篇文章主要介绍了spring整合redis以及使用RedisTemplate的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • response.setContentType()参数以及作用详解

    response.setContentType()参数以及作用详解

    这篇文章主要介绍了response.setContentType()参数以及作用详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • SpringBoot2.x 参数校验问题小结

    SpringBoot2.x 参数校验问题小结

    这篇文章主要介绍了SpringBoot2.x 参数校验一些问题总结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • 如何处理后台向前台传递的json数据

    如何处理后台向前台传递的json数据

    这篇文章主要介绍了如何处理后台向前台传递的json数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • RocketMQ实现消息分发的步骤

    RocketMQ实现消息分发的步骤

    RocketMQ 实现消息分发的核心机制是通过 Topic、Queue 和 Consumer Group 的配合实现的,下面给大家介绍RocketMQ实现消息分发的步骤,感兴趣的朋友一起看看吧
    2024-03-03
  • Spring使用注解方式实现创建对象

    Spring使用注解方式实现创建对象

    这篇文章主要介绍了Spring使用注解方式实现创建对象,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2023-02-02
  • 23种设计模式(1) java单例模式

    23种设计模式(1) java单例模式

    这篇文章主要为大家详细介绍了23种设计模式之java单例模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • 你应该知道的这些Mybatis-Plus使用技巧(小结)

    你应该知道的这些Mybatis-Plus使用技巧(小结)

    这篇文章主要介绍了你应该知道的这些Mybatis-Plus使用技巧(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Java swing仿酷狗音乐播放器

    Java swing仿酷狗音乐播放器

    这篇文章主要为大家详细介绍了Java swing实现音乐播放器,Java开发图形界面程序音乐播放器仿酷狗音乐播放器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06

最新评论