垃圾回收的核心知识点解析

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

Java运行时内存中的程序计数器、虚拟机栈、本地方法栈这三部分区域其生命周期与相关线程有关,随线程而生,随线程而灭。而程序计数器就是一个单纯存地址的整数也不需要关心,因此我们GC(垃圾回收)的主要目标就是堆(堆中存放着几乎所有实例对象)!

检测垃圾

一个对象,如果后续不再被使用且没有引用指向它,就可以认为是垃圾。
有以下方法可知对象是否有引用指向:

引用计数算法

在主流的JVM中没有选用引用计数法来管理内存,最主要的原因就是引用计数法无法解决对象的循环引用问题 Python,PHP采取了引用计数算法。

给对象增加一个引用计数器,每当有一个地方引用它时,计数器就+1;当引用失效时,计数器就-1;任何时刻计数器为0的对象就是不能再被使用的,即可被回收。

        Test test1 = new Test();
        Test test2 = test1;
        Test test3 = test1;
        Test test4 = test1;

垃圾回收的核心知识点解析,JavaEE,java,jvm,java-ee,后端

此算法存在两个缺陷:

  1. 浪费内存空间
  2. 存在循环引用的情况
    用一个例子来解释一下循环引用的问题:
class Test {
 public Test test;
}
        Test test1 = new Test();
        Test test2 = new Test();
        test1.test=test2;
        test2.test=test1;

垃圾回收的核心知识点解析,JavaEE,java,jvm,java-ee,后端
此时test1与test2 销毁了,两个对象的引用计数分别减一。
垃圾回收的核心知识点解析,JavaEE,java,jvm,java-ee,后端
此时这两个对象的引用计数不为0,不能作为垃圾且无法使用,陷入了一个逻辑上的循环。

可达性分析算法

通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称之为"引用链",当一个对象到GC Roots没有任何的引用链相连时(从GC Roots到这个对象不可达)时,证明此对象是不可用的

垃圾回收的核心知识点解析,JavaEE,java,jvm,java-ee,后端
在java中,可作为GC Roots(垃圾回收根对象)的对象有以下几种:

  1. 栈上的局部变量
  2. 常量池中引用的对象
  3. 方法区中类静态属性引用的对象

只有从GC Roots对象开始,通过引用链可达的对象才被认为是存活的,而无法通过引用链访问的对象则会被判定为垃圾,并进行回收。

缺点:

  1. 遍历开销:可达性分析算法需要遍历整个对象图以确定每个对象的可达性。对于大型堆和复杂的引用关系,遍历开销可能非常大,特别是在全局垃圾回收中。这可能会导致垃圾回收的性能下降。
  2. 延迟回收:可达性分析算法需要遍历整个对象图,从GC Roots开始,逐个检查每个对象的引用关系。这个过程可能需要消耗大量的时间,且在垃圾回收期间,应用程序的执行会被暂停(STW - Stop-The-World)。因此,可达性分析算法可能导致较高的延迟,影响程序的响应性能。

回收垃圾

标记清除算法

算法分为"标记"和"清除"两个阶段 : 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
回收前:
垃圾回收的核心知识点解析,JavaEE,java,jvm,java-ee,后端
回收后:
垃圾回收的核心知识点解析,JavaEE,java,jvm,java-ee,后端
垃圾回收的核心知识点解析,JavaEE,java,jvm,java-ee,后端
不足:

  1. 标记和清除这两个过程的效率都不高。
  2. 标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行中需要分配较大对象时,无法找到足够连续内存而不得不提前触发另一次垃圾收集。

复制算法

"复制"算法是为了解决"标记-清理"的效率问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
简单来说复制算法就是把不是垃圾的对象拷贝到未使用的那一边,然后再统一释放刚才使用过的那一块区域

缺点:

  1. 内存利用率比较低。
  2. 如果当前区域的大部分对象都需要保留垃圾很少,那么此时的复制成本就比较高。

标记整理算法

标记整理算法的基本流程:

  1. 标记:从根对象开始,通过可达性分析算法,标记所有从根对象可达的存活对象。标记过程中,通常使用标记位(标记状态)来标记对象是否为存活对象。

  2. 整理:将所有存活对象移到堆的一端,紧凑排列,以便释放出连续的一段内存空间。在移动存活对象时,需要更新对这些对象的引用,确保引用指向移动后的新位置。

  3. 更新引用:在堆中,遍历所有存活对象的引用,将其指向新的位置。这是为了避免悬挂指针(引用指向被移动或已回收的对象)的问题。

  4. 释放未标记的对象:在整理后的堆中,所有没有被标记的对象都可以被认为是垃圾对象,可以直接被回收。

优点:解决了内存碎片问题。
缺点:搬运复制开销比较大。

分代算法

分代算法主要基于一种观察:大部分对象的生命周期都比较短暂。根据这个观察,分代算法将堆内存划分为不同的代(Generation),每一代中对象的生命周期不同,并且根据对象的生命周期将不同的垃圾回收策略应用于不同的代中。

一般来说,分代堆内存被划分为年轻代(Young Generation)和老年代(Old Generation)两个主要部分
年轻代
年轻代是存放新创建的对象的地方,大部分对象在创建后很快就变为垃圾对象。年轻代通常进一步分为Eden区和两个Survivor区。新创建的对象首先放入Eden区,当Eden区满时,不会被回收的对象会被转移到一个Survivor区。当一个Survivor区满时,其中的存活对象会被复制到另一个Survivor区或者老年代。经过多次垃圾回收后依然存活的对象将晋升到老年代。
年轻代通常采用复制算法(Copying)作为垃圾回收策略,因为新创建的对象的生命周期短暂,复制算法可以更好地利用对象的特点。
老年代
老年代是存放存活时间较长的对象的地方,老年代的对象生命周期较长,垃圾回收频率相对较低。对于老年代的垃圾回收,可以采用标记-清除(Mark-Sweep)或者标记-整理(Mark-Compact)等算法。

分代算法通过区分不同代的对象,针对不同代采取不同的垃圾回收策略,可以提高垃圾回收效率和系统性能。年轻代的频繁垃圾回收可以快速回收新创建对象,老年代的较少回收可以减少全局垃圾回收的引发,提高应用程序的响应性。这种分代垃圾回收策略在大多数的垃圾收集器中都有应用。文章来源地址https://www.toymoban.com/news/detail-564716.html

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

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

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

相关文章

  • Java核心知识点1-java和c++区别、隐式和显示类型转换

    java和c++区别 java通过虚拟机实现跨平台特性,但c++依赖于特定的平台。 java没有指针,它的引用可以理解为安全指针,而c++和c一样具有指针。 java支持自动垃圾回收,而c++需要手动回收。 java不支持多重继承,只能通过实现多个接口来达到相同目的,而c++支持多继承。  隐式(

    2024年02月03日
    浏览(46)
  • PyFlink核心知识点

    四层 说明 备注 SteamGraph 代码生成的最初的图 表示程序的拓扑结构 JobGraph 将多个符合条件的节点,链接为一个节点 可以减少数据在节点之间流动所需要的序列化/反序列化/传输消耗 ExecutionGraph JobGraph的并行化版本 是调度层最核心的数据结构 PhysicalGraph JobManager根据ExecutionGra

    2024年04月27日
    浏览(51)
  • Vue入门——核心知识点

    Vue是一套用于 构建用户界面 的 渐进式 JS框架。 构建用户界面:就是将后端返回来的数据以不同的形式(例如:列表、按钮等)显示在界面上。 渐进式:就是可以按需加载各种库。简单的应用只需要一个核心库即可,复杂的应用可以按照需求引入各种Vue插件。 采用组件化模式

    2024年02月06日
    浏览(52)
  • 一文吃透Tomcat核心知识点

    首先,看一下整个架构图。最全面的Java面试网站 接下来简单解释一下。 Server :服务器。Tomcat 就是一个 Server 服务器。 Service :在服务器中可以有多个 Service,只不过在我们常用的这套 Catalina 容器的Tomcat 中只包含一个 Service,在 Service 中包含连接器和容器。一个完整的 Serv

    2024年02月02日
    浏览(46)
  • JavaSE核心基础-循环-知识点

    1.循环概念 循环是在满足条件的情况下,反复的做同一件事。 Java语言中的循环语句有三种,分别是for语句、while语句和do-while语句。程序中需要循环处理时,程序员要根据实际问题,选择适当的循环语句。解决循环问题时一定要找到循环条件和循环操作。 2.for循环语句格式

    2024年02月22日
    浏览(40)
  • redis核心知识点简略笔记

    value数据类型 string 二进制安全 list 有序、可重复 set 无序、不重复 hash field-value的map sorted set 不重复、通过double类型score分数排序 场景 string 计数器 缓存 分布式锁 访问频率控制 分布式session hash 购物车等对象属性灵活修改 list 定时排行榜 set 收藏 sorted set 实时排行榜 持久化

    2024年02月13日
    浏览(50)
  • 【大数据】Hudi 核心知识点详解(二)

    😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点赞 🧡、关注 💛、收藏 💚)!!!您的支持 💖💖💖 将激励 🔥 博主输出更多优质内容!!! Hudi 核心知识点详解(一) Hudi 核心知识点详解(二) Hudi 提供了 Hudi 表的概念,这些表支持

    2024年02月03日
    浏览(38)
  • 【MQ 系列】RabbitMq 核心知识点小结

    RabbitMQ 是一个基于 AMQP 协议实现的企业级消息系统,想要顺畅的玩耍的前提是得先了解它,本文将主要介绍 rabbitmq 的一些基本知识点 特点 基本概念 消息投递消费的几种姿势 事务 集群 它是采用 Erlang 语言实现的 AMQP(Advanced Message Queued Protocol)的消息中间件,最初起源于金融系

    2024年01月23日
    浏览(38)
  • 关于“Python”的核心知识点整理大全63

    目录 20.2.11 使用 Git 跟踪项目文件 1. 安装Git 2. 配置Git 3. 忽略文件 .gitignore 注意 4. 提交项目 20.2.12 推送到 Heroku 注意 20.2.13 在 Heroku 上建立数据库 20.2.14 改进 Heroku 部署 1. 在Heroku上创建超级用户 注意 注意 如果你阅读完了第17章,就知道Git是一个版本控制程序,让你能够在每次

    2024年01月25日
    浏览(30)
  • 关于“Python”的核心知识点整理大全11

    目录 ​编辑 6.2.4 修改字典中的值  6.2.5 删除键—值对 注意 删除的键—值对永远消失了。  6.2.6 由类似对象组成的字典 6.3 遍历字典 6.3.1 遍历所有的键—值对 6.3.2 遍历字典中的所有键 往期快速传送门👆(在文章最后): 6.2.4 修改字典中的值 要修改字典中的值,可依次指定

    2024年02月05日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包