关于JVM的垃圾回收GC的一些记录

目录

一、JVM内存区域划分

 二、从一个基本问题开始引入垃圾回收

三、GC作用的区域

三、如何确定一个对象是否可以被当成垃圾进行回收

(1)引用计数法

(2)可达性分析算法

(3)引用的类型

(3.1)强引用(Strong Reference)

(3.2)软引用(Soft Reference)

(3.3)弱引用(Weak Reference)

(3.4)虚引用(Phantom Reference)

(3.5)终结器引用(Final Reference)

(4)垃圾回收器的大致工作流程

四、垃圾回收算法

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

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

(3)复制算法

五、堆的不同区域(分代垃圾回收)

六、堆的不同区域使用不同的垃圾回收算法

七、垃圾回收器

1. 有哪些垃圾回收器

2. CMS垃圾回收器和G1垃圾回收器

八、其它一些说明

JVM相关参数


一、JVM内存区域划分

 二、从一个基本问题开始引入垃圾回收

        从一个基本问题思考,既然要进行垃圾回收,那么可定要从某一个区域(内存区域)进行回收(即,把内存区域中的某些对象当成垃圾,把这些垃圾对象占用的内存区域回收回来,从而释放内存,避免这个区域的内存被占满)。

        通过以上一个基本的问题出发,我们可以明确如下几个问题:

(1)在哪个区域上进行垃圾回收(换句话说:JVM的哪个区域可以执行垃圾回收这个动作);

(2)在这个可以执行垃圾回收的区域中,如何识别出哪些对象是垃圾;

(3)确定了哪些对象可以被当成垃圾进行回收,那么应该使用什么算法进行回收;

(4)针对这个可以执行垃圾回收的区域,此区域又可以分为哪些不同的小区域,各个小区域应该使用哪种垃圾回收算法;

        针对以上几个问题,下面逐一进行说明:

三、GC作用的区域

       JVM(Java虚拟机)的垃圾回收主要是针对堆内存进行的。堆内存是用来存储对象实例的地方,而垃圾回收的主要任务就是识别并清除不再被任何活跃对象引用的对象,从而释放它们占用的内存空间。因此,垃圾回收器主要关注的是堆内存中的对象,以确保内存的有效利用和系统性能的提高。

三、如何确定一个对象是否可以被当成垃圾进行回收

        既然已经知道了,垃圾回收是针对堆内存的,那么如何判断堆内存中的哪些对象可以被当成垃圾进行回收呢?有如下几种方法:

(1)引用计数法

        每个对象都会有一个与之关联的引用计数器,用来记录指向该对象的引用数量;当一个对象被引用时,其引用计数加一;当一个对象的引用被释放时,其引用计数减一。当引用计数为0时,表示没有任何引用指向该对象,即可被视为垃圾对象,可以被回收。

        尽管引用计数法简单直观,但也存在一些问题,例如无法处理循环引用的情况(如:当两个或多个对象互相引用导致引用计数不为零)。由于这一缺陷,现代的Java虚拟机一般不再使用引用计数法作为判断对象可以是否被当成垃圾的依据,而是采用基于可达性分析的算法来判断对象是否可以被当成垃圾进行回收。

(2)可达性分析算法

        Java虚拟机中的垃圾回收器采用可达性分析算法来探索所有存活的对象。问题来了,如何进行探索呢?

        是通过扫描堆中的对象,看是否能够沿着 GC Root 对象为起点的引用链找到该对象,找不到,表示可以回收;但是问题又来了,哪些对象可以作为 GC Root对象呢?

        可以使用 Eclipse(没错,就是哪个被IDEA打趴下的Eclipse)提供的一个工具(Memory Analyzer (MAT))进行查看(这个工具需要结合 JDK提供的 jmpa 工具进行使用),MAT分析工具官方下载链接:Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation

(3)引用的类型

        上面提到了<引用>,在Java中,有如下几种引用类型:

(3.1)强引用(Strong Reference)

        强引用是最常见的引用类型,在代码中使用最频繁。当我们使用new关键字创建一个对象时,默认就是强引用。只要强引用存在,垃圾回收器就不会回收被引用的对象。即使内存不足时,系统也会抛出OutOfMemoryError异常而不是回收强引用对象。

        【只有所有GC Roots 对象都不通过【强引用】引用该对象后,该对象才能被垃圾回收】

(3.2)软引用(Soft Reference)

        软引用是一种相对强引用较弱的引用类型。通过SoftReference类来实现。当内存不足时,Java虚拟机会根据一定的策略来决定是否回收软引用对象。通常情况下,只有在内存不足且没有强引用指向该对象时,才会回收软引用对象。软引用适用于对内存敏感的缓存等场景。

        【仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收,回收软引用对象】

        【可以配合引用队列来释放软引用自身】

(3.3)弱引用(Weak Reference)

        弱引用(Weak Reference):弱引用是一种比软引用更弱的引用类型。通过WeakReference类来实现。当垃圾回收器进行回收时,无论内存是否充足,只要弱引用对象没有被强引用指向,就会被回收。弱引用常用于实现对象注册表、缓存等场景。

        【仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象】

        【可以配合引用队列来释放弱引用自身】

(3.4)虚引用(Phantom Reference)

        虚引用是最弱的引用类型之一。通过PhantomReference类来实现。虚引用的作用是在对象被回收之前,允许程序员在对象被回收时收到一个系统通知。虚引用无法通过引用访问对象,而是通过ReferenceQueue来获取相关通知。虚引用常与引用队列(ReferenceQueue)一起使用,用于某些特定的清理操作。

        【必须配合引用队列使用,主要配合ByteBuffer使用,被引用对象回收时,会将虚引用入队,由Reference Handler 线程调用虚引用相关方法释放直接内存

(3.5)终结器引用(Final Reference)

        终结器引用是一种比较特殊的引用类型。当对象具有终结器(Finalizer)时,它会被分配给一个终结器引用。终结器引用的主要作用是在对象销毁前,通过执行终结器方法进行资源释放和清理。然而,终结器的使用已不推荐,因为它们具有不确定性和性能问题,应尽量避免使用。

        【无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由Finalizer线程通过终结器引用找到被引用对象并调用它的finalize方法,第二次GC时才能回收被引用对象】

(4)垃圾回收器的大致工作流程

(1)根搜索:垃圾回收器会从一组称为"GC Roots"的起始点开始遍历,例如虚拟机栈中的引用、静态变量等。任何能从GC Roots开始遍历到的对象都被认为是活跃对象,不会被回收;

(2)可达性分析:从GC Roots出发,遍历堆中的对象图,标记所有被引用的对象为活跃对象;

(3)清除阶段:遍历整个堆,将未被标记为活跃对象的对象标记为垃圾,并进行回收。

        注意:JVM使用了不同的垃圾回收算法,例如标记-清除、标记-整理和复制算法等。这些算法的具体实现细节可能会有所不同,但基本的判断原则都是通过可达性分析来确定对象是否可回收。

        此外,Java还提供了finalize()方法,允许对象在被回收之前执行特定的清理操作。但是,由于finalize()方法的执行时机不确定且开销较大,因此在实际应用中,建议使用显式的资源释放方式,如使用try-with-resources语句块来确保及时释放资源。

四、垃圾回收算法

        既然确定了哪些对象可以被当作垃圾进行回收,那么应该使用怎样的方法进行垃圾回收呢?换句话说,使用什么垃圾回收算法呢?

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

示意图:

标记阶段(Marking Phase)

        从根对象(如全局变量和活跃线程的栈和寄存器)开始,通过遍历对象之间的引用关系,标记所有能够被访问到的对象。在这个阶段,所有被标记的对象被视为活动对象,而未被标记的对象则被视为垃圾对象。 

清除阶段(Sweeping Phase)

        标记阶段之后,系统会对堆中的所有对象进行线性遍历,清除未被标记的对象,并将它们所占用的内存空间进行释放。这样就完成了对垃圾对象的回收工作。

优点:

  • 简单直观,能够有效地回收不再使用的内存对象

缺点:

  • 内存碎片化问题和回收效率问题(由于清除阶段释放了大量的内存空间,留下了不连续的内存碎片,可能会导致内存分配时的碎片化问题)
  • 此外,标记-清除算法在执行过程中会停止整个应用程序(Stop the world, STW),可能会导致较长的停顿时间,影响了应用程序的响应速度。

        因此,在实际应用中,往往会结合其他垃圾回收算法,如压缩算法(Compaction)、分代算法(Generational Collection)等,来解决标记-清除算法存在的问题,以提高内存管理的效率和性能。 

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

示意图:

标记-整理算法有如下几个阶段:

标记(Mark)

        从根对象出发,遍历整个对象图,标记所有活跃对象。活跃对象是指仍然被引用的对象,而非垃圾对象。

整理(Compact)

        将所有活跃对象向内存的一端移动,紧凑排列,以便在后续步骤中形成连续的可用内存空间。

清除(Sweep)

        从堆的另一端开始,将未被标记的对象视为垃圾,将其回收,并释放相应的内存空间。

更新引用:

        在整理过程中,由于对象的位置发生了变化,需要更新所有对对象的引用,确保引用指向正确的内存地址。

优点:

        标记-整理算法的优点是可以大幅减少内存碎片的产生,提高内存的利用率

缺点:

        它需要进行整理和移动对象的操作,可能会引入较大的停顿时间,影响应用程序的响应性能。因此,该算法通常适用于较小的堆内存或对停顿时间要求较低的场景。

(3)复制算法

示意图:

复制算法有如下几个步骤:

  1. 将内存空间分为两个相等的区域:From区和To区。
  2. 在From区中分配内存并创建对象。
  3. 当From区的内存耗尽时,启动垃圾回收机制。
  4. 从From区中将存活的对象复制到To区。
  5. 清空From区中的所有对象,并交换From区和To区的角色。

        复制算法的优点在于简单高效,它解决了标记-清除算法和标记-整理算法中会产生的内存碎片问题。但是,由于需要将存活对象复制到另一块区域,因此复制算法会导致内存利用率降低一半(需要双倍的内存空间),适用于新生代的内存回收,不适合用于老年代的大规模对象回收。

        因此,在JVM中,通常会将堆内存划分为新生代老年代,新生代主要使用复制算法来进行垃圾回收,而老年代则会采用其他更适合的算法,例如标记-整理算法或标记-清除算法。

五、堆的不同区域(分代垃圾回收)

        分代回收算法是JVM的一种垃圾回收算法,基于对象的生命周期,将堆内存分为不同的代(Generation),并对不同代采用适合的垃圾回收算法。通常将堆内存划分为新生代、老年代和持久代(或元数据区),其中新生代又可以进一步划分为Eden区、Survivor区1和Survivor区2

        分代回收算法的主要思想是:大部分对象的生命周期很短,很快就会被回收,而只有少数对象的生命周期很长,需要在堆内存中存活较长时间。因此,我们可以采用不同的垃圾回收算法来针对不同的对象生命周期,以达到更好的性能和效果。

        在分代回收算法中,新生代通常使用复制算法进行垃圾回收,因为大多数对象的生命周期较短,而老年代则采用标记-整理算法或标记-清除算法,因为老年代中的对象生命周期更长,需要更高效的回收算法。而持久代主要存储类元数据信息等不会被回收的数据,一般不需要进行垃圾回收。

        分代回收算法的优点在于根据对象的生命周期采用不同的回收算法,可以更好地平衡垃圾回收的效率和停顿时间(STW),并减少不必要的内存复制和整理操作。但是,分代回收算法需要更多的内存空间来划分不同的代,而且需要更复杂的垃圾回收机制来管理不同代之间的引用关系,因此在实际应用中需要根据具体情况进行选择和配置。

以下是学习黑马视频-JVM教程截的图

六、堆的不同区域使用不同的垃圾回收算法

        通过《五、堆的不同区域(分代垃圾回收)》可知:

  1. 新生代通常使用复制算法进行垃圾回收,因为大多数对象的生命周期较短;
  2. 老年代则采用标记-整理算法或标记-清除算法,因为老年代中的对象生命周期更长,需要更高效的回收算法。
  3. 持久代主要存储类元数据信息等不会被回收的数据,一般不需要进行垃圾回收。

七、垃圾回收器

Oracle官方文档:Available Collectors (oracle.com)

1. 有哪些垃圾回收器

 

2. CMS垃圾回收器和G1垃圾回收器

CMS(Concurrent Mark Sweep)垃圾回收器和G1(Garbage-First)垃圾回收器都是Java虚拟机的垃圾回收器,它们在内存管理和垃圾回收策略上有一些区别。

  1. 并发性能:CMS垃圾回收器是一种以最短停顿时间为目标的垃圾回收器。它使用并发标记和并发清理的方式来实现垃圾回收,可以在垃圾回收过程中与应用程序并发执行,减少停顿时间,提高系统的响应能力。而G1垃圾回收器也具有并发标记和并发清理的特性,但相比CMS,G1进一步改进了并发性能,通过将堆内存划分为多个小块(Region),并采用增量式的方式进行垃圾回收,可以更好地控制每次垃圾回收的时间。

  2. 内存模型:CMS垃圾回收器使用的是分代回收的思想,将堆内存划分为年轻代和老年代。年轻代使用复制算法进行垃圾回收,老年代使用标记-清除算法。而G1垃圾回收器则是基于分区(Region)的内存模型,将整个堆内存划分为多个相等大小的区域,并且不再明确区分年轻代和老年代。G1会根据垃圾回收的情况动态地选择进行回收的区域。

  3. 碎片整理:CMS垃圾回收器在进行垃圾回收时,不会对整个堆内存进行整理,因此可能会导致堆内存的碎片化问题。而G1垃圾回收器采用了分区的方式,并在垃圾回收过程中进行了部分的碎片整理,可以较好地避免堆内存的碎片化问题。【注意:G1垃圾回收器(1)同时注重吞吐量(Throughput)和低延迟(Low latency),默认的暂停目标是 200 ms;(2)超大堆内存,会将堆划分为多个大小相等的 Region;(3)整体上是 标记+整理 算法,两个区域之间是 复制 算法 ;(4)相关JVM参数:< -XX:+UseG1GC >   < -XX:G1HeapRegionSize=size >  < -XX:MaxGCPauseMillis=time >

  4. 停顿时间:CMS垃圾回收器通过并发的方式来减少垃圾回收的停顿时间,但无法完全避免停顿。而G1垃圾回收器则通过控制每次垃圾回收的时间和并发执行的阶段,可以更好地控制全局的垃圾回收时间,并且具有更可预测的停顿时间。

综上所述,CMS垃圾回收器和G1垃圾回收器都是面向低停顿时间的垃圾回收器,但G1相比CMS在并发性能、内存模型、碎片整理和停顿时间上都有进一步的改进和优化。根据具体的应用场景和需求,可以选择适合的垃圾回收器来进行内存管理。

        JDK 1.8默认使用的垃圾回收器是ParallelGC,也称为Parallel Scavenge收集器。这是一种基于标记-复制算法的垃圾回收器,主要针对年轻代进行垃圾回收。ParallelGC使用多个线程并行地进行垃圾回收操作,可以充分利用多核CPU的优势,以提高垃圾回收的效率。

        另外,在JDK 1.8中还引入了G1垃圾回收器,它是一种基于分区(Region)的垃圾回收器,相比于ParallelGC具有更好的并发性能和更可预测的停顿时间。但G1不是默认的垃圾回收器,需要通过特定参数进行配置才能启用。

        需要注意的是,JDK 1.8中的垃圾回收器并不是固定的,可以通过虚拟机参数进行配置。在实际应用中,需要根据具体的场景和需求来选择合适的垃圾回收器。

八、其它一些说明

JVM相关参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/267168.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Netty Review - Netty自动重连机制揭秘:原理与最佳实践

文章目录 概述Pre客户端自动重连CodeServerClient (重点) 测试启动自动重连运行过程中断链后的自动重连 概述 Pre Netty Review - 深入探讨Netty的心跳检测机制&#xff1a;原理、实战、IdleStateHandler源码分析 客户端自动重连 自动重连是一个用于提高网络应用稳定性和可靠…

OpenSource - SCM服务管理平台

文章目录 官方网址文档下载版本功能解决了哪些问题使用对象优势Linxu版本scm-dev deb服务列表 Windows版本scm-dev 服务列表scm-all 服务列表scm-jdk 服务列表scm-springboot 精简版本服务列表scm-springboot 服务列表scm-tomcat 服务列表 SCM 截图 官方网址 https://scm.chus…

如何更好的去理解源码

前言 这篇文章我准备来聊一聊如何去阅读开源项目的源码。 在聊如何去阅读源码之前&#xff0c;先来简单说一下为什么要去阅读源码&#xff0c;大致可分为以下几点原因&#xff1a; 最直接的原因&#xff0c;就是面试需要&#xff0c;面试喜欢问源码&#xff0c;读完源码才可以…

代码随想录-刷题第三十六天

435. 无重叠区间 题目链接&#xff1a;435. 无重叠区间 思路&#xff1a;本题与452. 用最少数量的箭引爆气球非常像&#xff0c;弓箭的数量就相当于是非交叉区间的数量&#xff0c;只要把弓箭那道题目代码里射爆气球的判断条件加个等号&#xff08;认为[0&#xff0c;1][1&am…

Kafka集群架构服务端核心概念

目录 Kafka集群选举 controller选举机制 Leader partition选举 leader partition自平衡 partition故障恢复机制 follower故障 leader故障 HW一致性保障 HW同步过程 Epoch Kafka集群选举 1. 在多个broker中, 需要选举出一个broker, 担任controller. 由controller来管理…

深入理解 Git 分支管理:提升团队协作与开发效率

目录 前言1 什么是分支2 分支的好处2.1 并行开发的支持2.2 独立性与隔离性2.3 灵活的版本控制2.4 提高安全性和代码质量2.5 项目历史的清晰记录 3 Git 分支操作命令3.1 git branch -v3.2 git branch 分支名称3.3 git checkout 分支名称3.4 git merge 分支名称3.5 git rebase 分…

RabbitMQ的概念与使用

什么是MQ&#xff1f; MQ 是消息队列&#xff08;Message Queue&#xff09;的简称。消息队列是一种应用程序间通信的方式&#xff0c;用于在不同的应用程序之间传递消息。它通过解耦发送者和接收者之间的直接依赖关系&#xff0c;提供了一种异步、可靠的消息传递机制。 什么是…

爬虫是什么?起什么作用?

【爬虫】 如果把互联网比作一张大的蜘蛛网&#xff0c;数据便是放于蜘蛛网的各个节点&#xff0c;而爬虫就是一只小蜘蛛&#xff0c;沿着网络抓取自己得猎物&#xff08;数据&#xff09;。这种解释可能更容易理解&#xff0c;官网的&#xff0c;就是下面这个。 爬虫是一种自动…

红日靶场-2

目录 前言 外网渗透 外网渗透打点 1、arp探测 2、nmap探测 3、nikto探测 4、gobuster目录探测 WebLogic 10.3.6.0 1、版本信息 2、WeblogicScan扫描 3、漏洞利用 4、哥斯拉连接 内网渗透 MSF上线 1、反弹连接 2、内网扫描 3、frpc内网穿透 4、ms17-010 5、ge…

第十三章 常用类(包装类和 String 相关类)

一、包装类 1. 包装类的分类 &#xff08;1&#xff09;针对八种基本数据类型相应的引用类型—包装类 &#xff08;2&#xff09;有了类的特点&#xff0c;就可以调用类中的方法。 2. 包装类和基本数据类型的转换 &#xff08;1&#xff09;jdk5 前的手动装箱和拆箱方式 publ…

Unity预设体

目录 预设体是什么&#xff1f; 如何创建预设体&#xff1f; 如何修改预设体&#xff1f; 如何删除预设体&#xff1f; 预设体是什么&#xff1f; Unity中的预设体&#xff08;Prefab&#xff09;是一种可重复使用的游戏对象模板。它允许开发者创建一个或多个游戏对象&…

模型评估系列:回归模型的评估指标介绍和代码实践

文章目录 1. 简介2. 回归评估指标2.1 平均绝对误差&#xff08;MAE&#xff09;2.2 均方误差&#xff08;MSE&#xff09;2.3 均方根误差&#xff08;RMSE&#xff09;2.4 R平方&#xff08;决定系数&#xff09;2.5 调整后的R平方2.6 交叉验证的R22.7 回归评估指标 - 结论 3 设…

OpenCV-10mat的深浅拷贝

一.Mat介绍 mat是OpenCV是在C语言用来表达图像数据的一种数据结构&#xff0c;在Python转换为numpy的ndarray. mat是由header和date组成&#xff0c;header中记录了图片的维数、大小、数据类型等信息. 例如&#xff1a;cv2.imshow&#xff08;winname&#xff0c; mat&#…

基于Boosting的力扣题目建模分析

基于Boosting的力扣题目建模分析 1 背景介绍2 数据说明3 描述性分析3.1 分类问题描述性分析3.2 回归问题描述性分析 4 建模分析4.1 Boosting概述4.2 AdaBoost算法4.2.1 算法概述4.2.2 算法实现 4.3 提升树算法4.3.1 算法概述4.3.2 算法实现 5 总结 1 背景介绍 随着大数据、人工…

2024 年全球顶级的 4 款 PDF 转换器软件

PDF 是一种广泛使用的共享文档和文件的格式。但是&#xff0c;有时您可能需要将 PDF 文件转换为其他格式&#xff08;例如 Word 或 Excel&#xff09;&#xff0c;以便编辑或操作内容。这就是 PDF 转换器软件派上用场的地方。 有许多 PDF 转换器软件可供选择&#xff0c;有免费…

day06

文章目录 一、流程控制1. 作用2. 分类1&#xff09;顺序结构2&#xff09;选择结构1. if语句2. switch语句 3&#xff09;循环结构 二、函数1. 作用2. 语法3. 使用4. 匿名函数5. 作用域 一、流程控制 1. 作用 控制代码的执行顺序 2. 分类 1&#xff09;顺序结构 从上到下依…

openGauss学习笔记-170 openGauss 数据库运维-备份与恢复-导入数据-更新表中数据-使用合并方式更新和插入数据

文章目录 openGauss学习笔记-170 openGauss 数据库运维-备份与恢复-导入数据-更新表中数据-使用合并方式更新和插入数据170.1 前提条件170.2 操作步骤 openGauss学习笔记-170 openGauss 数据库运维-备份与恢复-导入数据-更新表中数据-使用合并方式更新和插入数据 在用户需要将…

T-Dongle-S3开发板信息

相关学习网站 ESP32保姆级教程开始学习ESP32_哔哩哔哩_bilibili Wokwi - Online ESP32, STM32, Arduino Simulator T-Dongle-S3 资料:https://spotpear.cn/index/study/detail/id/1069.html 主控芯片&#xff1a; ESP32-S3 Xtensa 芯片集成了 Xtensa 32 位 LX7 双核处理器…

数据校园服务管理系统,教育平台可视化界面(教育资源信息化PS文件)

大屏组件可以让UI设计师的工作更加便捷&#xff0c;使其更高效快速的完成设计任务。现分享大数据校园服务管理系统、科技教育平台大数据可视化界面、教育资源信息化大数据分析等Photoshop源文件&#xff0c;文末提供完整资料&#xff0c;供UI设计师们工作使用。 若需其他 大屏…

手机无人直播的兴起

近年来&#xff0c;随着科技的不断进步和智能手机的普及&#xff0c;手机无人直播成为了一种新兴的传媒方式。手持手机&#xff0c;不经过镜头操作人员的干预&#xff0c;通过直播平台实时分享自己的所见所闻&#xff0c;成为了越来越多人的选择。手机无人直播的盛行离不开以下…