【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失去对第一个对象的引用,引用计数为1System.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引用obj2obj2.obj = obj1; // obj2引用obj1obj1 = 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则会根据堆空间的利用率和各个分区的情况来决定回收时机。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++学习笔记3

A. 求出那个数 题目描述 喵喵是一个爱睡懒觉的姑娘&#xff0c;所以每天早上喵喵的妈妈都花费很大的力气才能把喵喵叫起来去上学。 在放学的路上&#xff0c;喵喵看到有一家店在打折卖闹钟&#xff0c;她就准备买个闹钟回家叫自己早晨起床&#xff0c;以便不让妈妈这么的辛苦…

Caddy2使用阿里云DNS申请https证书,利用阿里云DNS境内外不同解析给Gone文档做一个同域名的国内镜像站点

我从头到尾实现了一个Golang的依赖注入框架&#xff0c;并且集成了gin、xorm、redis、cron、消息中间件等功能&#xff1b;自己觉得还挺好用的&#xff0c;并且打算长期维护&#xff01; github地址&#xff1a;https://github.com/gone-io/gone 文档原地址&#xff1a;https:/…

2024CCPC郑州站超详细题解(含题面)ABFHJLM(河南全国邀请赛)

文章目录 前言A Once In My LifeB 扫雷 1F 优秀字符串H 随机栈J 排列与合数L Toxel 与 PCPC IIM 有效算法 前言 这是大一博主第一次参加xcpc比赛&#xff0c;虽然只取得了铜牌&#xff0c;但是收获满满&#xff0c;在了解了和别人的差距后会更加激励自己去学习&#xff0c;下面…

Python从0到POC编写--函数

数学函数&#xff1a; 1. len len() 函数返回对象&#xff08;字符、列表、元组等&#xff09;长度或项目个数&#xff0c; 例如&#xff1a; str "python" len(str)2. range range() 函数返回的是一个可迭代对象&#xff08;类型是对象&#xff09;&#xff0c;…

并行执行的4种类别——《OceanBase 并行执行》系列 4

OceanBase 支持多种类型语句的并行执行。在本篇博客中&#xff0c;我们将根据并行执行的不同类别&#xff0c;分别详细阐述&#xff1a;并行查询、并行数据操作语言&#xff08;DML&#xff09;、并行数据定义语言&#xff08;DDL&#xff09;以及并行 LOAD DATA 。 《并行执行…

vm虚拟机扩容centos磁盘内存

1.查看虚拟机扩展前磁盘内存 df -h 2.关机情况下扩展磁盘内存 3.对扩容的磁盘分区 fdisk /dev/sda 输入n新增分区&#xff0c;回车&#xff0c;选择p&#xff0c;回车 为分区设置分区格式&#xff0c;在Fdisk命令处输入&#xff1a;t 分区号用默认 3&#xff08;或回车&…

OSS证书自动续签,一分钟轻松搞定,解决阿里云SSL免费证书每3个月失效问题

文章目录 一、&#x1f525;httpsok-v1.11.0支持OSS证书自动部署介绍支持特点 二、废话不多说上教程&#xff1a;1、场景2、实战Stage 1&#xff1a;ssh登录阿里云 ECSStage 2&#xff1a;进入nginx &#xff08;docker&#xff09;容器Stage 3&#xff1a;执行如下指令Stage 3…

测试环境搭建整套大数据系统(十六:超级大文件处理遇到的问题)

一&#xff1a;yarn出现损坏的nodemanger 报错现象 日志&#xff1a;1/1 local-dirs usable space is below configured utilization percentage/no more usable space [ /opt/hadoop-3.2.4/data/nm-local-dir : used space above threshold of 90.0% ] ; 1/1 log-dirs usabl…

01-02-2

1、typedef的使用 a.语法 typedef 原名 别名&#xff1b;。 ​ typedef struct student {int num;char name[20];char sex; }stu,*pstu;//stu相当于struct student这个类型&#xff0c;*pstu相当于struct student * 别名的理解方法&#xff1a;若是字母前面有符号&#xff0…

SOUI4里使用字体回退

在新版本的SOUI里render-skia导出了一个新的函数用于字体回退功能。Render_Skia_SetFontFallback 函数原型如下&#xff1a; EXTERN_C void SOUI_COM_API Render_Skia_SetFontFallback(FontFallback fontFallback);因为我的工程是使用动态库&#xff0c;这里可以直接获取到这…

如何用微信小程序实现远程控制4路控制器/断路器

如何用微信小程序实现远程控制4路控制器/断路器呢&#xff1f; 本文描述了使用微信小程序调用HTTP接口&#xff0c;实现控制4路控制器/断路器&#xff0c;支持4路输出&#xff0c;均可独立控制&#xff0c;可接入各种电器。 可选用产品&#xff1a;可根据实际场景需求&#xf…

内容与图像一对多问题解决

场景复现 分析&#xff1a; 其实这是两给表&#xff0c;一个内容表&#xff0c;一个图片表&#xff0c;一对多的关系。 解决思路: 1. 先上传图片拿到图片的List集合ids&#xff0c;返回值是集合的ids&#xff0c;给到前端 2. 再添加内容表的数据生成了id&#xff0c;遍历查…

佳博打印机如何设置打印模式为热敏模式

1、打开电脑搜索框&#xff0c;如下图输入打印机: 2、点击打印机设置&#xff0c;如下图&#xff1a; 3、点击打印机首选项&#xff0c;如下图&#xff1a; 4、点击下图“卷”进行设置 也可对打印机间距高度进行调整

【深度学习】探秘PSD:合成到真实去雾框架的实例解析

揭秘PSD&#xff1a;合成到真实去雾框架的革新 一、PSD框架的提出背景二、PSD框架的原理与网络结构三、PSD框架的实现与代码示例四、结论与展望 在图像处理领域&#xff0c;去雾技术一直是一个备受关注的研究热点。然而&#xff0c;传统的去雾方法在面对真实世界的模糊图像时&a…

腐烂的橘子

代码实现&#xff1a; int orangesRotting(int **grid, int gridRowSize, int *gridColSizes) {int good 0, bad 0, t 0;for (int i 0; i < gridRowSize; i) {for (int j 0; j < gridColSizes[0]; j) {if (grid[i][j] 1) { // 记录好橘子数good;} else if (grid[i…

ABB机器人程序类型介绍

ABB机器人编程语言为rapid语言&#xff0c;在例行程序中可分为三类&#xff1a;普通程序、功能程序和中断程序。例如新建一个例行程序&#xff0c;会选择一个程序类型&#xff0c;三种类型的区别如下&#xff1a; 1、普通程序&#xff08;procedures&#xff09;&#xff1a;常…

代码大师的工具箱:现代软件开发利器

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

Ubuntu 超级终端Terminator常用使用技巧

Ubuntu 超级终端Terminator常用使用技巧 Terminator 是一款功能强大的终端模拟器&#xff0c;它特别适合于需要同时管理多个终端会话的用户。以下是如何在 Ubuntu 上使用 Terminator 的详细指南&#xff1a; 安装 Terminator 如果你的系统尚未安装 Terminator&#xff0c;你…

anaconda 环境配置

官方网站下载地址&#xff1a; https://www.anaconda.com/download/ 国内清华镜像下载地址&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 配置国内环境: conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ …

人工智能生成图像的兴起:区分事实与虚构

人工智能生成图像的兴起&#xff1a;区分事实与虚构 概述 在人工智能 (AI) 已融入我们日常生活的时代&#xff0c;人工智能生成图像的快速发展引发了人们对数字内容真实性的担忧。最近&#xff0c;人工智能生成的图像甚至欺骗了最敏锐的眼睛&#xff0c;这引发了人们对批判性…