【JAVA】JAVA的垃圾回收机制详解

对于Java的垃圾回收机制,它是Java虚拟机(JVM)提供的一种自动内存管理机制,主要负责回收不再使用的对象以释放内存空间。垃圾回收机制主要包括以下几个方面的内容:

  • 垃圾对象的识别:Java虚拟机通过一些算法(如引用计数法、可达性分析法等)来识别不再使用的对象,这些对象被认为是垃圾对象。
  • 垃圾回收算法:Java虚拟机使用不同的垃圾回收算法来回收内存,常见的有标记-清除算法、复制算法、标记-整理算法等。
  • 垃圾回收器:Java虚拟机中有多种不同的垃圾回收器,如Serial收集器、Parallel收集器、CMS收集器、G1收集器等,它们各自具有不同的特点和适用场景。
  • 内存回收时机:垃圾回收器会在一定条件下触发内存回收,比如当堆内存达到一定阈值、程序执行完毕时、调用System.gc()方法时等。

需要注意的是,全局变量的生命周期与整个应用程序的生命周期相同,因此如果全局变量引用的对象一直存在于内存中而不被释放,可能会造成内存泄漏。因此,在使用全局变量时要合理管理其生命周期,确保不再需要时及时释放,以减少内存占用和提高系统性能。

【JAVA】JAVA的垃圾回收机制

    • 一、垃圾对象的识别
      • 1.1、引用计数法
        • 1.1.1、原理:
        • 1.1.2、示例:
      • 1.2、可达性分析法
      • 1.2.1、原理:
      • 1.2.2、示例:
    • 二、垃圾回收算法
      • 2.1、Java的垃圾回收算法主要包括以下几种:
      • 2.2、常用:标记-清除算法之三色标记
        • 2.2.1、原理:
        • 2.2.2、具体的工作流程如下:
    • 三、垃圾回收器
    • 四、内存回收时机

一、垃圾对象的识别

Java对垃圾对象的识别是通过垃圾回收器(Garbage Collector)实现的。垃圾回收器主要依靠两种机制来识别垃圾对象:引用计数法和可达性分析法。下面我会详细介绍这两种机制的原理,并举例说明。

1.1、引用计数法

引用计数法是一种简单的垃圾回收算法,它基于对象的引用计数来判断对象是否是垃圾对象。每个对象都会有一个引用计数器,当有引用指向对象时,引用计数加一;当引用失效或对象被释放时,引用计数减一。当对象的引用计数为零时,表示对象不再被引用,可以被回收。

注意:引用计数法在Java中并不常用,因为它无法解决循环引用的问题,容易造成内存泄漏。两个对象互相引用,这样每一个对象的引用都是1,构成了循环引用,但是并不能被其他对象访问,这两个对象再无任何引用,引用计数算法也就无法回收它们。

1.1.1、原理:

当程序中的某个对象没有任何引用指向它时,它的引用计数会变为零。
垃圾回收器会定期扫描内存中的对象,检查它们的引用计数
引用计数为零的对象被判定为垃圾对象,可以进行回收。

1.1.2、示例:
class MyClass {
    public static void main(String[] args) {
        MyClass obj1 = new MyClass();
        MyClass obj2 = new MyClass();
        
        // obj1和obj2分别引用两个对象
        obj1 = null; // obj1失去对第一个对象的引用,引用计数为1
        System.gc(); // 手动触发垃圾回收
    }
}

1.2、可达性分析法

可达性分析法是Java常用的垃圾回收算法,它基于对象的可达性来判断对象是否是垃圾对象。该算法从一组称为"根"的起始对象开始,通过对象之间的引用链追踪,能够到达的对象称为“可达对象”,不能到达的对象即为“垃圾对象”。

1.2.1、原理:

垃圾回收器从一组根对象开始,例如静态变量、局部变量、常量池等。
通过对象之间的引用关系,追踪可达对象,构成可达图(Reachability Graph)。
无法通过引用链到达的对象被判定为垃圾对象,可以进行回收。

1.2.2、示例:

class MyClass {
    public static MyClass obj; // 静态变量作为根对象
    
    public static void main(String[] args) {
        MyClass obj1 = new MyClass();
        MyClass obj2 = new MyClass();
        
        obj1.obj = obj2; // obj1引用obj2
        obj2.obj = obj1; // obj2引用obj1
        
        obj1 = null; // obj1失去引用,但obj2还可达
        obj2 = null; // obj2也失去引用,整个链断裂
        
        System.gc(); // 手动触发垃圾回收
    }
}

在这个示例中,obj1和obj2通过相互引用形成了一个循环引用,但由于它们都已经失去了外部引用,整个循环链都是不可达的,因此可以被判定为垃圾对象。

总的来说,Java的垃圾回收机制通过引用计数法和可达性分析法来识别垃圾对象,保证了内存的自动管理和释放。在实际编程中,多数情况下采用的是可达性分析法,因为它能够处理循环引用等复杂情况,并且不容易出现误判。

二、垃圾回收算法

2.1、Java的垃圾回收算法主要包括以下几种:

  • 标记-清除算法(Mark and Sweep):这是最基本的垃圾回收算法之一。它分为两个阶段:标记阶段和清除阶段。标记阶段遍历所有可达对象,并标记为活动对象;清除阶段则将未标记的对象进行清除。该算法的缺点是会产生内存碎片,影响内存的连续分配。

  • 标记-整理算法(Mark and Compact):这个算法结合了标记-清除算法和复制算法的优点。它首先标记出所有活动对象,然后将它们向一端移动,然后清除掉端部之外的内存空间。这种方式既避免了内存碎片,又不需要额外的内存空间进行复制。

  • 增量式算法(Incremental):这种算法将垃圾回收过程分为多个阶段,在每个阶段中分别完成标记、清除等操作。这样可以将整个垃圾回收过程分摊到多个时间段,减少了单次垃圾回收的停顿时间。

  • 分代算法(Generational):这种算法根据对象的生命周期将内存分为多个代(Generation),通常分为年轻代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation)。新创建的对象会被分配到年轻代,经过几次垃圾回收后仍然存活的对象会被提升到老年代。这样可以根据对象的特点采用不同的垃圾回收策略,提高垃圾回收效率

  • 复制算法(Copying):这个算法将内存分为两个区域:活动区和闲置区。当活动区满了后,将活动区中的存活对象复制到闲置区,然后清空活动区。这种方式避免了内存碎片的问题,但是需要额外的内存空间来进行复制。

2.2、常用:标记-清除算法之三色标记

三色标记算法是一种用于垃圾回收的标记-清除算法。它基于分为三种颜色的标记来管理对象的存活状态,这些颜色通常表示对象的可达性:

2.2.1、原理:
  • 白色:表示对象未被访问,即尚未进行标记。
  • 灰色:表示对象已经被访问,但其引用的对象尚未遍历访问。
  • 黑色:表示对象已经被访问,且其引用的对象已经遍历访问过。

三色标记算法主要用于并发垃圾回收器,如CMS GC(并发标记清除垃圾回收器)和G1 GC(G1垃圾回收器)。它通过在垃圾回收过程中对对象进行颜色标记,以确定对象的可达性和存活状态,从而进行垃圾回收操作。

2.2.2、具体的工作流程如下:
  • 初始标记阶段(Initial Marking):在这个阶段,垃圾回收器首先会标记出根对象和直接与根对象相连的对象,将它们标记为灰色。
  • 并发标记阶段(Concurrent Marking):在初始标记阶段之后,垃圾回收器会启动并发标记阶段,同时与应用程序线程并发执行。在这个阶段,垃圾回收器会遍历访问灰色对象引用的对象,并将它们标记为灰色。被标记过的对象则变为黑色。
  • 重新标记阶段(Remark):在并发标记阶段完成后,可能会有一些新产生的对象被引用,或者有一些灰色对象引用的对象发生了变化。因此,需要进行重新标记阶段,遍历访问这些对象,将其标记为灰色或黑色。
  • 重复上面过程直到没有灰色
  • 并发清除阶段(Concurrent Sweep):最后是并发清除阶段,垃圾回收器会并发执行清除操作,将未被标记为黑色的对象清除,并回收它们所占用的内存空间。

三色标记算法通过不同颜色的标记来实现并发的垃圾回收过程,尽可能地减少了垃圾回收的停顿时间,提高了系统的响应性能。
在这里插入图片描述

在实际应用中,Java的垃圾回收器通常会根据不同的场景和应用程序特点选择合适的垃圾回收算法。例如,年轻代通常采用复制算法,老年代采用标记-清除或标记-整理算法。 Java的垃圾回收器包括串行垃圾回收器(Serial GC)、并行垃圾回收器(Parallel GC)、并发标记清除垃圾回收器(CMS GC)、G1垃圾回收器等,它们各自采用不同的垃圾回收算法和策略。

三、垃圾回收器

  1. Serial GC(串行垃圾回收器):Serial GC是最基本的垃圾回收器,在启动Java应用时可以通过设置JVM参数来指定使用Serial GC。示例命令如下:

    java -XX:+UseSerialGC YourMainClass
    

    这条命令将Java应用使用Serial GC进行垃圾回收。Serial GC适合用于单核CPU和小型应用场景。

  2. Parallel GC(并行垃圾回收器):Parallel GC可以通过设置JVM参数来启用。示例命令如下:

    java -XX:+UseParallelGC YourMainClass
    

    这条命令将Java应用使用Parallel GC进行垃圾回收。Parallel GC适合用于多核CPU和对系统资源要求较高的应用场景。

  3. CMS GC(并发标记清除垃圾回收器):CMS GC也可以通过设置JVM参数来启用。示例命令如下:

    java -XX:+UseConcMarkSweepGC YourMainClass
    

    这条命令将Java应用使用CMS GC进行垃圾回收。CMS GC适用于对响应时间要求较高的应用场景。

  4. G1 GC(G1垃圾回收器):G1 GC同样可以通过设置JVM参数来启用。示例命令如下:

    java -XX:+UseG1GC YourMainClass
    

    这条命令将Java应用使用G1 GC进行垃圾回收。G1 GC适用于大型、内存密集型应用场景。

  5. ZGC(低延迟垃圾回收器):ZGC需要在支持的平台上使用,可以通过设置JVM参数来启用。示例命令如下:

    java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC YourMainClass
    

    这条命令将Java应用使用ZGC进行垃圾回收。ZGC适用于对停顿时间要求极低的应用场景。

  6. Shenandoah GC(低停顿时间垃圾回收器):Shenandoah
    GC同样需要在支持的平台上使用,可以通过设置JVM参数来启用。示例命令如下:

    java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC YourMainClass
    

    这条命令将Java应用使用Shenandoah GC进行垃圾回收。Shenandoah GC适用于对停顿时间要求极低的应用场景。

四、内存回收时机

在JVM里,将堆区划分为两个区域,新生代和老年代,分别用来存放新生成的对象和长期存在的对 象。于是也有了分别针对这两个区域的GC。而这两个区域的GC又是分层的,在新生代的GC后内存仍然不够才有可能触发老年代的GC。

Java中的内存回收时机通常由垃圾回收器(Garbage Collector,GC)来决定,而不是由程序员手动控制。GC会在以下情况下触发内存回收:

  1. 内存空间不足:当Java虚拟机检测到堆内存空间不足时,会触发垃圾回收。这种情况通常包括两种情形:

    • 堆空间不足:指的是新对象无法分配到足够的内存空间。

    • 老年代空间不足:指的是老年代对象无法得到足够的空间来存放。

      老年代的GC,又称为FullGC。分场景来说,FullGC在这些情况下会被触发:

      • 发生Young GC之前进行检查,如果“老年代可用的连续内存空间” < “新生代历次Young GC后升入老年代的对象总和的平均大小”,说明本次Young GC后可能升入老年代的对象大小,可能超过了老年代当前可用内存空间,此时会触发FullGC
      • 当老年代没有足够空间存放对象时,会触发一次FullGC

      Eden区域刚开始的设置并没有到达Xmx的最大,会有一个初始值,不够用的时候先扩展一些可扩充空间,仍然不够的时候也会触发young gc。在这里插入图片描述
      在这里插入图片描述
      触发老年代的回收
      在这里插入图片描述

  2. 程序显式调用System.gc():虽然程序员可以调用System.gc()方法请求垃圾回收,但Java虚拟机并不保证会立即执行垃圾回收操作,而是由虚拟机自行决定是否进行回收。

  3. 永久代空间不足(Java 8及之前版本):在Java 8及之前的版本中,永久代(PermGen)用于存放类的元数据等信息。当永久代空间不足时,也会触发垃圾回收。

  4. 对象生命周期结束:当对象不再被引用或者引用被置为null时,它就成为了不可达对象(Unreachable Objects),这些对象会被垃圾回收器识别并回收。

  5. 垃圾回收器的策略:不同的垃圾回收器具有不同的触发条件和策略,比如CMS GC会根据内存的使用情况和回收频率来触发回收,G1 GC则会根据堆空间的利用率和各个分区的情况来决定回收时机。

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

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

相关文章

element ui的table多选

使用el-table的selection-change事件来获取选中的值&#xff1b; 例&#xff1a; html代码&#xff1a; <el-button type"primary" click"openTableSet">列表设置</el-button><!-- 列表设置弹框 --> <el-dialog :close-on-click-mo…

替代UCC21550隔离式双通道栅极驱动器

描述 PC86320是一个隔离的双通道栅极驱动器具有可编程死区时间和宽温度范围。它设计有5A峰值源和6A峰值吸收电流来驱动电源高达2MHz的MOSFET、SiC、GaN和IGBT晶体管开关频率。PC86320可以配置为两个低端驱动器&#xff0c;两个高边驱动器&#xff0c;或具有可编程功能的半桥驱…

二叉树的广度优先遍历 - 华为OD统一考试(D卷)

OD统一考试(D卷) 分值: 200分 题解: Java / Python / C++ 题目描述 有一棵二叉树,每个节点由一个大写字母标识(最多26个节点)。 现有两组字母,分别表示后序遍历(左孩子->右孩子->父节点)和中序遍历(左孩子->父节点->右孩子)的结果,请输出层次遍历的结…

世界上知名度最高的人物颜廷利:精神与物质的对岸有五种类型的人

世界上知名度最高的人物颜廷利&#xff1a;精神与物质的对岸有五种类型的人 面对现实生活中的物质生活和精神生活而言&#xff0c;确切的说&#xff0c;实际上总共可以划分为五种类型的人&#xff1a; 第一种&#xff0c;隔河观望的人&#xff0c;他们总是以‘物质’&#xff0…

英语学习笔记8——What‘s your job?

What’s your job? 你是做什么工作的&#xff1f; 词汇 Vocabulary policeman 男警察 policewoman 女警察 police n. 警力 集合名词&#xff0c;永表复数 西方国家警察管的事很多。交警&#xff0c;刑警&#xff0c;武警一般不分开。 taxi driver 出租车司机 taxi / cab n.…

QA测试开发工程师面试题满分问答22: (干货)为什么要加锁Lock,举个例子说说

加锁原因 下面代码会有什么问题&#xff1f; import threading import requests from queue import Queuedef make_request(url, params, results_queue):response requests.get(url, paramsparams)result {url: url,params: params,response: response.text}results_queue…

新型AI Stable Artisan横空出世?

StabilityAI宣布推出Stable Artisan 前言 就在今天&#xff0c;Stability AI宣布推出 Stable Artisan&#xff0c;让更广泛的受众能够使用 Stability AI 的 Developer Platform API 功能。Stable Artisan 具有他们的高级型号&#xff0c;例如 Stable Diffusion 3、Stable Video…

宇宙数字扩展全球业务,设立欧洲和亚洲分支机构

2024年4月18日 宇宙数字蚂蚁矿机今日宣布在欧洲和亚洲设立新的分支机构,这一举措旨在进一步强化公司的全球服务网络,提供更地道的客户支持和更快的物流服务,以提升用户满意度。 新的分支机构将位于欧洲和亚洲的战略性城市,为当地客户提供更快速和更便捷的服务。通过本地化的客…

记一次springboot jpa更新复杂几何类型报错Only simple geometries should be used

问题&#xff1a; 更新数据时&#xff0c; 几何字段MultiPolygon类型时报错&#xff1b; java.lang.IllegalStateException: Only simple geometries should be used 几何字段Point类型时不报错&#xff1b; 新增时字段存在MultiPolygon不报错。 查看日志可知&#xff0c;…

重磅!一款实景三维建模软件官宣免费开放

近日&#xff0c;RealityCapture推出了1.4版本。新版本除了常规功能的新增和修复外&#xff0c;更为重磅的是推出了新的定价模式&#xff01;RealityCapture1.4版本官宣。将对学生、教育工作者、业余爱好者和年收入低于100万美元的公司免费提供&#xff0c;而且还是所有功能&am…

Java Swing游戏开发学习27

内容来自RyiSnow视频讲解 这一节讲的是Equip & Use Items装备与使用物品。 前言 实现捡起物品、切换武器装备、使用物品。 修复问题 当光标在物品栏&#xff08;背包&#xff09;中移动到没有物品的格子中的时候&#xff0c;使装备介绍子窗口不可见&#xff0c;反之可见…

CSS-浮动

float (浮动) 作用&#xff1a;盒子的顶点是一样的&#xff0c;具备行内块的特征&#xff0c;能设置宽高 属性&#xff1a;float 属性值&#xff1a;left 浮动在网页左边 right 浮动在网页右边 .a{width: 100px;height: 100px;float:left;background-color: red;}.b…

云手机:海外舆情监控的新工具

在数字化时代&#xff0c;海外舆情监控对于企业、品牌和政府机构来说&#xff0c;已经变得至关重要。传统的舆情监控方法往往受限于地域、设备和技术&#xff0c;而云手机的出现&#xff0c;为海外舆情监控带来了全新的解决方案。 一、云手机与海外舆情监控的完美结合 云手机作…

一个开源即时通讯源码

一个开源即时通讯源码 目前已经含服务端、PC、移动端即时通讯解决方案&#xff0c;主要包含以下内容。 服务端简介 不要被客户端迷惑了&#xff0c;真正值钱的是服务端&#xff0c; 服务是采用Java语言开发&#xff0c;基于spring cloud微服务体系开发的一套即时通讯服务端。…

华为eNSP学习—IP编址

IP编址 IP编址子网划分例题展示第一步:机房1的子网划分第二步:机房2的子网划分第三步:机房3的子网划分IP编址 明确:IPv4地址长度32bit,点分十进制的形式 ip地址构成=网络位+主机位 子网掩码区分网络位和主机位 学此篇基础: ①学会十进制与二进制转换 ②学会区分网络位和…

Python批量备份华为设备配置到FTP服务器

Excel表格存放交换机信息&#xff1a; 备份文件夹效果图&#xff1a; Windows系统配置计划任务定时执行python脚本&#xff1a; Program/script&#xff1a;C:\Python\python.exe Add arguments (optional)&#xff1a; D:\Python_PycharmProjects\JunLan_pythonProje…

能源系统升级BACnet IP分布式I/O边缘模块深度整合

能源管理系统(EMS)的高效运行成为了实现绿色建筑、节能减排的关键。而BACnet IP分布式远程I/O模块作为这一系统中的重要组件&#xff0c;正发挥着不可小觑的作用。本文将以某大型商业综合体为例&#xff0c;探讨BACnet IP I/O模块如何在能源管理中大显身手。 商业综合体涵盖办公…

揭秘APP广告变现:轻松赚取额外收入!

在移动应用&#xff08;APP&#xff09;的世界中&#xff0c;变现能力是衡量一个应用成功与否的关键指标之一。无论是个人开发者还是企业团队&#xff0c;如何通过应用创造收入&#xff0c;始终是一个备受关注的话题。今天&#xff0c;我们将深入探讨APP广告变现的路径&#xf…

【ElementUI -- 优化小技巧系列】 -- el-tree 节点内容过长优化 以及选中默认节点

在使用elementui过程中经常碰到关于样式的问题&#xff0c;我曾经很喜欢通过类名修改css样式来做&#xff0c;其实原生封装的elementui库的样式对于普通开发来说已经足够了&#xff0c;通过类名修改css只会让组件臃肿难以维护&#xff0c;现在真的越来越怕写css&#xff0c;经常…

镜舟科技亮相2024中国移动算力网络大会、Qcon、DTC等多项活动

在刚刚过去的 4 月份&#xff0c;镜舟科技受邀参与一系列技术交流活动&#xff0c;与移动云、金科创新社、infoQ、墨天轮、开科唯识等媒体及合作伙伴展开积极交流&#xff0c;并分享其在数据技术、金融等垂直行业领域的创新实践&#xff0c;从产业侧、业务侧、技术侧洞察需求、…