jvm垃圾回收算法有哪些_jvm垃圾回收过程

jvm垃圾回收算法有哪些_jvm垃圾回收过程JVM垃圾回收算法两个概念:新生代:存放生命周期较短的对象的区域。老年代:存放生命周期较长的对象的区域。相同点:都在Java堆上1.标记–清除算法执行步骤:标记:遍历内存区域,对需要回收的对象打上标记。清除:再次遍历内存,对已经标记过的内存进行回收。图解:缺点:效率问题;遍历了两次内存空间(第一次标记,第二次清除)。空间问题:容易产生大量内存碎片,当再需要一块比…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

JVM垃圾回收算法

Java应用程序不用程序员手动管理内存中的垃圾回收,是因为JVM有专门的垃圾回收线程做这件事。当内存不够用时,会自动触发回收。为了在效率和内存碎片之间均衡,衍生出了一系列的垃圾回收算法。

1.标记–清除算法

执行步骤:

  • 标记:遍历整个内存区域,对需要回收的对象打上标记。
  • 清除:再次遍历内存,对标记过的内存进行回收。
图解:

在这里插入图片描述
在这里插入图片描述

缺点:

  • 效率问题;遍历了两次内存空间(第一次标记,第二次清除)。
  • 空间问题:容易产生大量内存碎片,当再需要一块比较大的内存时,虽然总的可用内存是够的,但是由于太过分散,无法找到一块连续的且满足分配要求的,因而不得不再次触发一次GC。

2.复制算法

将内存划分为等大的两块,每次只使用其中的一块。当一块用完了,触发GC时,将该块中存活的对象复制到另一块区域,然后一次性清理掉这块没有用的内存。下次触发GC时将那块中存活的的又复制到这块,然后抹掉那块,循环往复。

图解:

在这里插入图片描述

在这里插入图片描述

优点

  • 相对于标记–清理算法解决了内存的碎片化问题,因为复制的时候,会把存活的对象,聚拢在一起。
  • 效率更高(清理内存时,记住首尾地址,一次性抹掉)。

缺点:

  • 内存利用率不高,每次只能使用一半内存。8G的内存,只能使用4G,这个是无法接受的。
改进

研究发现,大多数对象都是“朝生夕死”的,即生命周期非常短。也就是说,在发生GC的时侯,其实大多数对象已经是待回收的了,还处于正常状态的对象很少。因为存活的特别少,所以在进行复制的时候,复制的对象就特别少,占用的空间也就特别小,完全不需要1:1划分内存空间。多了也是浪费,够分配就行(特殊情况不够存放再说)。
但是也有一部分对象生命周期特别长,比如缓存中的对象,还有一些别的对象等等。对于这些对象如果每次都要复制移动的话,就显的特别麻烦。另外如果某些对象特别大,如果复制的话,也放不下。因此根据对象的特点进行了分治。将整个堆划分为两大块:新生代和老年代,分别用于存放不同特点的对象。
在这里插入图片描述
新生代呢,存放生命周期短的对象及其体积小的对象。
老年代呢 ,存放生命周期长的 ,体积大的对象。
而且对于新生代和老年代采用了不同的垃圾回收算法。新生代使用复制算法:

将整个新生代按照8 : 1 : 1的比例划分为三块,最大的称为Eden(伊甸园)区,较小的两块分别称为To Survivor和From Survivor。

在这里插入图片描述

首次GC时,只需要将Eden存活的对象复制到To。然后将Eden区整体回收。再次GC时,将Eden和To存活的复制到From,循环往复这个过程。这样每次新生代中可用的内存就占整个新生代的90%,大大提高了内存利用率。

但不能保证每次存活的对象就永远少于新生代整体的10%,此时复制过去是存不下的。因此这里会用到老年代,进行分配担保,存不下的话将对象存储到老年代。若还不够,就会抛出OOM。另外如果一个对象在多次内存回收后,都还存活,也会进入老年代,这个次数通过
‐XX:+MaxTenuringThreshold控制,最大值为15.(对象头中的4个bit存放)。

3. 标记–整理算法

当对象的存活率比较高时,或者对象比较大时,用前面的复制算法这样复制过来,复制过去,没啥意义,且浪费时间。所以针对老年代提出了“标记整理”算法。

执行步骤:

  • 标记:对需要回收的进行标记
  • 整理:让存活的对象,向内存的一端移动,然后直接清理掉没有用的内存。
图解:

在这里插入图片描述
在这里插入图片描述

4、分代收集算法

分代收集算法其实没有什么新东西,就是上面新生代和老年代根据对象不同的特点,采用不同的算法进行回收,取名为分代收集。

对象怎样才会进入老年代呢?

  • 提升:当对象足够老的时候,会晋升到老年代。怎么才能足够老呢?对象在多次垃圾回收后,依然存活,也就是多次从from->to 又从to->from 这样多次。jvm认为无需让这样的对象继续这样复制,因此将其晋升到老年代。
  • 分配担保:默认的Survivor只占整个年轻代的10%,当从eden区复制到from / to的时候,存不下了,这个时候对象会被移动到老年代。-XX:PretenureSizeThreshold
  • 大对象直接在老年代分配。
  • 动态对象年龄判定:当eden区中,某一年龄的对象已经占用整个eden的一半了,那么大于或者等于这一年龄的对象都会进入老年代。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/194877.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号