java---垃圾回收算法(GC)

这篇具有很好参考价值的文章主要介绍了java---垃圾回收算法(GC)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、如何判断一个对象是否存活

1.引用计数法

2.可达性分析法

二、垃圾回收算法

1.标记清除法

2.复制算法

3.标记整理法

4.分代算法

具体流程

注意事项

空间分配担保原则

总结


一、如何判断一个对象是否存活

Java 堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些还存活,哪些已经" 死去 " 。判断对象是否已 " " 有如下几种算法:

1.引用计数法

给每一个对象设置一个引用计数器,当有一个地方引用该对象的时候,引用计数器就+1,引用失效时,引用计数器就-1;当引用计数器为0的时候,就说明这个对象没有被引用,也就是垃圾对象,等待回收; 缺点:无法解决循环引用的问题,当A引用B,B也引用A的时候,此时AB对象的引用都不为0,此时也就无法垃圾回收,所以一般主流虚拟机都不采用这个方法。

循环引用问题:

一个类:

Class Person{

 Person p;

一个方法:

void method(){

    Person s = new Person();   //此时该对象的引用数为1

   s.p = s;                                //此时该对象的引用数位2

}                                              //方法结束,引用 s  的生命结束,该对象的引用数位1

//此时该对象还被一个引用指向,但是我们无法拿到这个对象了,因为 引用 s 已经“死”了

2.可达性分析法

从一个被称为GC Roots的对象向下搜索,如果一个对象到GC Roots没有任何引用链相连接时,说明此对象不可用,在java中可以作为GC Roots的对象有以下几种:

1.虚拟机栈中引用的对象

2.方法区类静态属性引用的变量

3.方法区常量池引用的对象

4.本地方法栈JNI引用的对象

可达性图如下所示:

java---垃圾回收算法(GC)

二、垃圾回收算法

1.标记清除法

第一步:利用可达性去遍历内存,把存活对象和垃圾对象进行标记;第二步:在遍历一遍,将所有标记的对象回收掉;特点:效率不行,标记和清除的效率都不高;标记和清除后会产生大量的不连续的空间分片,可能会导致之后程序运行的时候需分配大对象而找不到连续分片而不得不触发一次GC。

2.复制算法

"复制"算法是为了解决"标记-清理"的效率问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。这样做的好处是每次都是对整个半区进行内存回收,内存分配时也就不需要考虑内存碎片等复杂情况,只需要移动堆顶指针,按顺序分配即可。此算法实现简单,运行高效。复制收集算法在对象存活率较高时会进行比较多的复制操作,效率会变低。

3.标记整理法

标记过程仍与 " 标记 - 清除 " 过程一致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。

4.分代算法

分代算法和上面讲的 3 种算法不同,分代算法是通过区域划分,实现不同区域和不同的垃圾回收策略,从而实现更好的垃圾回收。这就好比中国的一国两制方针一样,对于不同的情况和地域设置更符合当地的规则,从而实现更好的管理,这就时分代算法的设计思想。
当前 JVM 垃圾收集都采用的是 " 分代收集 (Generational Collection)" 算法,这个算法并没有新思想,只是根据对象存活周期的不同将内存划分为几块。一般是把Java 堆分为新生代和老年代。 在新生代中,每 次垃圾回收都有大批对象死去,只有少量存活,因此我们采用复制算法;而老年代中对象存活率高、没 有额外空间对它进行分配担保,就必须采用 " 标记 - 清理 " 或者 " 标记 - 整理 " 算法
堆内存划分如图:
java---垃圾回收算法(GC)

具体流程

1.对象优先在Eden分配。当 eden 区没有足够空间进行分配时,虚拟机将发起一次 Minor GC。

2.在 Eden 区执行了第一次 GC 之后,存活的对象会被移动到 form 分区;

3.Eden 区再次 GC,这时会采用复制算法,将 Eden 和 from 区一起清理,存活的对象会被复制到 to 区;    

4.当后续Eden又发生Minor GC的时候,会对Eden和 to 区进行垃圾回收,存活的对象复制到 from 区,并将Eden 和 to 区清空。

5.部分对象会在 from 和 to 区中来回的复制,如此的交换15次(由JVM参数 Max Tenuring Threshold 决定,默认是15),最终如果还是存活,就存入老年代。

6.Survivor 区内存不足会发生担保分配,超过指定大小的对象可以直接进入老年代(此时如果老年代的内存大小,小于对象的大小,可能会发生一次 Full GC,后面有提到)。

6.老年代满了而无法容纳更多的对象,Minor GC 之后通常就会进行Full GC,Full GC 清理整个内存堆 – 包括年轻代和老年代

注意事项

新生代:对于一般创建的对象都会进入。

老年代:对于大对象为了避免为大对象分配内存时由于分配担保机制带来的复制而降低效率;或者经过N次(一般是默认15次)的垃圾回收依然存活下来的对象;从新生代移动到老年代。

Minor GC、 Major GC、Full GC 的关系: 

1.Minor GC 又称为新生代GC:指的是发生在新生代的垃圾回收。因为Java对象大多都具备朝生夕灭的特性,因此Minor GC(采用的是复制算法)非常频繁,一般回收速度也比较的块。

2.Major GC 又称为老年代GC,一般的老年代GC,总是由于某次Minor GC 引起的,所以 Major GC 发生的时候也是 Full GC,可以看作他两个等效。

空间分配担保原则

如果YougGC时新生代有大量对象存活下来,而 survivor 区放不下了,这时必须转移到老年代中,但这时发现老年代也放不下这些对象了,那怎么处理呢?其实JVM有一个老年代空间分配担保机制来保证对象能够进入老年代。

在执行每次 YoungGC 之前,JVM会先检查老年代最大可用连续空间是否大于新生代所有对象的总大小。因为在极端情况下,可能新生代 YoungGC 后,所有对象都存活下来了,而 survivor 区又放不下,那可能所有对象都要进入老年代了。这个时候如果老年代的可用连续空间是大于新生代所有对象的总大小的,那就可以放心进行 YoungGC。但如果老年代的内存大小是小于新生代对象总大小的,那就有可能老年代空间不够放入新生代所有存活对象,这个时候JVM就会先检查 -XX:HandlePromotionFailure 参数是否允许担保失败,如果允许,就会判断老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小(就是每次从新生代到老年代的对象的平均大小),如果大于,将尝试进行一次YoungGC,尽快这次YoungGC是有风险的。如果小于,或者 -XX:HandlePromotionFailure 参数不允许担保失败,这时就会进行一次 Full GC。

在允许担保失败并尝试进行YoungGC后,可能会出现三种情况:

1.YoungGC后,存活对象小于survivor大小,此时存活对象进入survivor区中。

2. YoungGC后,存活对象大于survivor大小,但是小于老年大可用空间大小,此时直接进入老年代。

3. YoungGC后,存活对象大于survivor大小,也大于老年代可用空间大小,老年代也放不下这些对象了,此时就会发生“Handle Promotion Failure”,就触发了 Full GC。如果 Full GC后,老年代还是没有足够的空间,此时就会发生OOM内存溢出了。


总结

加油偶~~文章来源地址https://www.toymoban.com/news/detail-445945.html

到了这里,关于java---垃圾回收算法(GC)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 16、GC如何判断对象可以被回收

    引用计数法:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收, 可达性分析法:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的,那么虚拟机就判

    2024年02月16日
    浏览(41)
  • JVM | 垃圾回收器(GC)- Java内存管理的守护者

    在编程世界中, 有效的内存管理 是至关重要的。这不仅确保了应用程序的稳定运行,还可以大大提高性能和响应速度。作为世界上最受欢迎的编程语言之一,通过Java虚拟机内部的垃圾回收器组件来自动管理内存,是成为之一的其中一项必不可少的技术点。 在许多传统的编程

    2024年02月09日
    浏览(50)
  • 面试题:如何知道java对象被垃圾回收掉,用代码实现一个能监听对象被回收的功能

    Java中无法直接判断一个对象是否被垃圾回收掉,因为Java的垃圾回收机制是自动的,程序员并不需要手动清理对象。但是,如果我们想要知道一个对象何时被回收掉,可以使用 finalize() 方法。 每个Java对象都有一个 finalize() 方法,这个方法会在对象被垃圾回收前调用一次。我们

    2024年02月02日
    浏览(41)
  • 【JVM】垃圾回收 GC

    垃圾回收(Garbage Collection,GC)是由 Java 虚拟机(JVM)垃圾回收器提供的一种对内存回收的一种机制,它一般会在内存空闲或者内存占用过高的时候对那些没有任何引用的对象不定时地进行回收。以避免内存溢出和崩溃的问题。JVM的垃圾回收算法包括引用类型、引用计数器法

    2024年01月16日
    浏览(49)
  • JVM----GC(垃圾回收)详解

    Automatic Garbage Collection (自动垃圾回收)是JVM的一个特性,JVM会启动相关的线程,该线程会轮训检查heap memeory,并确定哪些是未被引用的(unreferenced),即未被使用的;哪些是被引用的(referenced),即正在使用的。 在C/C++语言中,对象内存的分配与回收,是手动进行分配与回收

    2024年02月09日
    浏览(45)
  • JVM:垃圾回收机制(GC)

    引用计数算法:         在对象中添加一个引用计数器,当每有一个地方引用它时,计数器值加一。当引用失效时,计数器值就减一。当一个对象的计数器为零时,表示该对象没有被任何其他对象引用,因此可以被释放。 优点 :是可以及时回收垃圾对象,避免内存泄漏,且

    2024年01月19日
    浏览(47)
  • 【JVM】垃圾回收机制详解(GC)

    可以看jvm详解之后,再来理解这篇文章更好 堆和方法区,主要发生在堆中,然后主要发生在堆的伊甸园区(Eden)。 Java中的垃圾回收是根据 可达性分析算法(Reachability Analysis) 和 引用计数算法 来判断对象是否存活的。 JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:

    2024年02月13日
    浏览(53)
  • 02JVM_垃圾回收GC

    在 堆 里面存放着java的所有对象实例,当对象为“死去”,也就是不再使用的对象,就会进行垃圾回收GC 1.1引用计数器 介绍 在对象中添加一个引用计数器,当一个对象被其他变量引用时这个对象的引用计数器加1。当某个变量不再引用这个对象时引用计数器减1。当这个引用计

    2024年02月09日
    浏览(39)
  • .NET CLR之垃圾回收(GC)

    公共语言运行库 (common language runtime,CLR) 是托管代码执行核心中的引擎。 运行库为托管代码提供各种服务,如跨语言集成、代码访问安全性、对象生存期管理、调试和分析支持。 它是整个.NET框架的核心,它为.NET应用程序提供了一个托管的代码执行环境。 它实际上是驻留在内

    2024年02月11日
    浏览(33)
  • 深入学习JVM —— GC垃圾回收机制

            前面荔枝已经梳理了有关JVM的体系结构和类加载机制,也详细地介绍了JVM在类加载时的双亲委派模型,而在这篇文章中荔枝将会比较详细地梳理有关JVM学习的另一大重点——GC垃圾回收机制的相关知识,重点了解的比如对象可达性的判断、四种回收算法、分代回收

    2024年02月14日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包