彻底搞懂JVM垃圾回收

jvm_garbage_collection

哈喽,大家好🎉,我是世杰

欢迎大家关注我的公众号『程序员世杰』获取更多后端技术干货🎉🎉!

本文我为大家介绍「JVM垃圾回收那些事

面试连环call

  1. 如何判断对象是否应被回收?
  2. finalize方法的实现机制是什么?
  3. 如何判断类应该被回收?
  4. 垃圾回收算法都有什么? 优缺点是什么?
  5. Minor GC, Major GC, Full GC 分别代表什么?
  6. JVM都有哪些内存分配策略?

1. 对象回收判断

1.1 引用计数算法

定义

一个对象被创建之后,系统会给这个对象初始化一个引用计数器,当这个对象被引用了,则计数器 +1,而当该引用失效后,计数器便 -1,直到计数器为 0,意味着该对象不再被使用了,则可以将其进行回收了。

存在问题

两个对象出现循环引用的情况下,此时引用计数器永远不为 0,导致无法对它们进行回收。

对象之间循环引用

1.2 可达性分析算法

定义

以 GC Roots 作为起始点进行搜索,一步步遍历找到和这个根对象具有引用关系的对象,然后再从这些对象开始继续寻找,能够到达到的对象都是存活的,不可达的对象可被回收。

image

在 Java 中 GC Roots 一般包含以下内容:

  • 虚拟机栈中引用的对象
  • 本地方法栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中的常量引用的对象

1.3 finalize()

对象可以被回收,就代表一定会被回收吗

即使在可达性分析法中不可达的对象,也并不是立刻回收。宣告一个对象死亡,至少要经历两次标记

第一次标记

如果对象进行可达性分析算法之后发现未与 GC Roots 引用链相连,那它将会第一次标记并且进行一次筛选。当对象没有覆盖 finalize () 方法、或者 finalize () 方法已经被 JVM 执行过,则判定为可回收对象。如果对象有必要执行 finalize () 方法,则被放入 F-Queue 队列中。稍后在 JVM 自动建立、低优先级的 Finalizer 线程(可能多个线程)中触发这个方法.

第二次标记

GC 对 F-Queue 队列中的对象进行二次标记。如果对象在 finalize () 方法中重新与引用链上的任何一个对象建立了关联,那么二次标记时则会将它移出 “即将回收” 集合。如果此时对象还没成功逃脱,那么只能被回收了。

注意 ⚠️:JDK9 版本及后续版本中各个类中的 finalize 方法会被逐渐弃用移除。忘掉它的存在吧!


2. 类回收判断

在大量使用反射、动态代理、CGLib 等 ByteCode 框架、动态生成 JSP 以及 OSGi 这类频繁自定义 ClassLoader 的场景都需要虚拟机具备类卸载功能,以保证不会出现内存溢出。

JVM方法区存储的是类信息,因此主要针对方法区进行类回收,那么如何判断一个类是无用的类的呢?

类需要同时满足下面 3 个条件才能算是 “无用的类”

  • 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
  • 加载该类的 ClassLoader 已经被回收。
  • 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

虚拟机可以对满足上述 3 个条件的无用类进行回收,这里说的仅仅是“可以”,而并不是和对象一样不使用就会必然被回收


3. 垃圾回收算法

3.1 标记-清除

将存活的对象进行标记,然后清理掉未被标记的对象。

这是一个非常基本的GC算法,它是现代GC算法的思想基础,分为标记和清除两个阶段:先把所有活动的对象标记(可达性分析法)出来,然后把没有被标记的对象统一清除掉

image

不足

  • 标记和清除过程效率都不高;
  • 会产生大量不连续的内存碎片,导致无法给大对象分配内存。

3.2 标记-整理

让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

标记—整理算法适用于存活对象较多的场合,它的标记阶段和标记-清除算法中的一样。整理阶段是将所有存活的对象压缩到内存的一端,之后清理边界外所有的空间。它的效率也不高。

image

3.3 复制

将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。

它比标记-清除算法要高效,但不适用于存活对象较多的内存,因为复制的时候会有较多的时间消耗。它的致命缺点是会有一半的内存浪费

image

现在的商业虚拟机都采用这种收集算法来回收新生代,但是并不是将新生代划分为大小相等的两块,而是分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 空间和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象一次性复制到另一块 Survivor 空间上,最后清理 Eden 和使用过的那一块 Survivor。

3.4 分代收集

现在的商业虚拟机采用分代收集算法,它根据对象存活周期将内存划分为几块,不同块采用适当的收集算法。

一般将堆分为新生代和老年代。

  • 新生代使用: 复制算法
  • 老年代使用: 标记-清除 或者 标记-整理 算法

新生代(Young Generation)

所有新生成的对象首先都是放在新生代的。新生代的目标就是尽可能快速的收集掉那些生命周期短的对象。

  • 新生代内存分配一块较大的 Eden 空间和两块较小的 Survivor 空间(默认 Eden 和 Survivor 的大小比例是 8:1)。每次使用 Eden 和其中一块 Survivor 空间(当Eden内存满了就会把对象分配到Survivor区
  • 回收时将 EdenSurvivor 空间中存活的对象一次性复制到另一块 Survivor 空间上。最后清理掉 Eden 和使用过的 Survivor 空间。Survivor 区总有一个是空的。
  • 如果另一块 Survivor 空间没有足够内存来存放上一次新生代收集下来的存活对象,那么这些对象则直接进入老年代。
  • 新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)。

img

老年代(Old Generation)

  • 在新生代中经历了 N 次垃圾回收后仍然存活的对象,就会被放到老年代中。因此,可以认为老年代中存放的都是一些生命周期较长的对象
  • 内存比新生代也大很多(大概比例是1:2),当老年代内存满时触发 Major 或者 Full GC,发生频率比较低,老年代对象存活时间比较长,存活率标记高

4. Minor GC、Major GC、Full GC

  • Minor GC/Young GC:只是新生代的垃圾收集

  • Major GC/Old GC:只是老年代的垃圾收集

    • 目前,只有 CMS GC 会有单独收集老年代的行为
    • 很多时候 Major GC 会和 Full GC 混合使用,需要具体分辨是老年代回收还是整堆回收
  • Mixed GC:收集整个新生代以及部分老年代的垃圾收集

    • 目前只有 G1 GC 会有这种行为
  • Full GC:收集整个 Java 堆和方法区的垃圾

img

对于 Minor GC,其触发条件非常简单,当 Eden 空间满时,就将触发一次 Minor GC。而 Full GC 则相对复杂,有以下条件:

  1. 调用 System.gc()

  2. 老年代空间不足

  3. 空间分配担保失败

  4. JDK 1.7 及以前的永久代空间不足

  5. Concurrent Mode Failure

注意 ⚠️:Concurrent Mode Failure 是 CMS 特有行为,执行 CMS GC 的过程中同时有对象要放入老年代,而此时老年代空间不足(可能是 GC 过程中浮动垃圾过多导致暂时性的空间不足),便会报 Concurrent Mode Failure 错误,并触发 Full GC。


5. 内存分配策略

JVM为对象分配内存时,会有一些分配策略保证更好的使用和回收对象

5.1 对象优先在 Eden 分配

  • 大多数情况下,对象在新生代 Eden 区分配,当 Eden 区空间不够时,发起 Minor GC。

5.2 大对象直接进入老年代

  • 大对象是指需要连续内存空间的对象,最典型的大对象是那种很长的字符串以及数组。

  • 经常出现大对象会提前触发垃圾收集以获取足够的连续空间分配给大对象。

  • -XX:PretenureSizeThreshold,大于此值的对象直接在老年代分配,避免在 Eden 区和 Survivor 区之间的大量内存复制。

5.3 长期存活的对象进入老年代

  • 为对象定义年龄计数器,对象在 Eden 出生并经过 Minor GC 依然存活,将移动到 Survivor 中,年龄就增加 1 岁,增加到一定年龄则移动到老年代中。

  • -XX:MaxTenuringThreshold 用来定义年龄的阈值。

5.4 动态对象年龄判定

  • 虚拟机并不是永远地要求对象的年龄必须达到 MaxTenuringThreshold 才能晋升老年代,如果在 Survivor 中相同年龄所有对象大小的总和大于 Survivor 空间的一半,则年龄大于或等于该年龄的对象可以直接进入老年代,无需等到 MaxTenuringThreshold 中要求的年龄。

5.5 空间分配担保

  • 在发生 Minor GC 之前,虚拟机先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果条件成立的话,那么 Minor GC 可以确认是安全的。

  • 空间分配担保是为了确保在 Minor GC 之前老年代本身还有容纳新生代所有对象的剩余空间。

  • 如果空间分配担保失败则会进行 Full GC

参考文章

【006】十分钟搞懂 Java 垃圾回收

Java 垃圾回收基础知识

JVM垃圾回收详解(重点)

JVM之垃圾回收机制(GC)


更多惊喜

我还将定期分享:

  • 最新互联网资讯:让你时刻掌握行业动态。

  • AI前沿新闻:紧跟技术潮流,不断提升自我。

  • 技术分享与职业发展:助你在职业生涯中走得更远、更稳。

  • 程序员生活趣事:让你在忙碌的工作之余找到共鸣与乐趣。

关注回复【1024】惊喜等你来拿!

点击查看惊喜

敬请关注【程序员世杰】

点击关注程序员世杰

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

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

相关文章

在Windows环境下安装pycharm

Python环境搭建 第一步下载安装python 等待安装完成 验证python是否安装成功 Python开发工具安装部署 JetBrains: Essential tools for software developers and teams PyCharm: the Python IDE for data science and web development 下载社区版本的PyCharm 双击打开下载好的…

python制作甘特图的基本知识(附Demo)

目录 前言1. matplotlib2. plotly 前言 甘特图是一种常见的项目管理工具,用于表示项目任务的时间进度 直观地看到项目的各个任务在时间上的分布和进度 常用的绘制甘特图的工具是 matplotlib 和 plotly 主要以Demo的形式展示 1. matplotlib 功能强大的绘图库&a…

nx上darknet的使用-目标检测-在python中的使用

1 内置的代码 在darknet中已经内置了两个py文件 darknet_video.py与darknet_images.py用法类似,都是改一改给的参数就行了,我们说一下几个关键的参数 input 要预测哪张图像weights 要使用哪个权重config_file 要使用哪个cfg文件data_file 要使用哪个da…

SQLite 命令行客户端 + HTA 实现简易UI

SQLite 命令行客户端 HTA 实现简易UI SQLite 客户端.hta目录结构V2V3参考资料 仅用于探索可行性&#xff0c;就只实现了 SELECT。 SQLite 客户端.hta <!DOCTYPE html> <html> <head><meta http-equiv"Content-Type" content"text/html;…

StarRocks分布式元数据源码解析

1. 支持元数据表 https://github.com/StarRocks/starrocks/pull/44276/files 核心类&#xff1a;LogicalIcebergMetadataTable&#xff0c;Iceberg元数据表&#xff0c;将元数据的各个字段做成表的列&#xff0c;后期可以通过sql操作从元数据获取字段&#xff0c;这个表的组成…

Java版Flink使用指南——从RabbitMQ中队列中接入消息流

大纲 创建RabbitMQ队列新建工程新增依赖编码设置数据源配置读取、处理数据完整代码 打包、上传和运行任务测试 工程代码 在《Java版Flink使用指南——安装Flink和使用IntelliJ制作任务包》一文中&#xff0c;我们完成了第一个小型Demo的编写。例子中的数据是代码预先指定的。而…

人工智能大模型如何助力电商产品经理打造高效的商品工业属性画像

摘要 商品工业属性画像是电商产品经理在进行商品管理、推荐、搜索、广告等业务时的重要依据。通过对商品的工业属性&#xff08;如品类、品牌、规格、功能、风格等&#xff09;的准确识别和标注&#xff0c;可以提高商品的展示效果、匹配度、转化率和用户满意度。然而&#xf…

如何为IP申请SSL证书

目录 以下是如何轻松为IP地址申请SSL证书的详细步骤&#xff1a; 申请IP证书的基本条件&#xff1a; 申请IP SSL证书的方式&#xff1a; 确保网络通信安全的核心要素之一&#xff0c;是有效利用SSL证书来加密数据传输&#xff0c;特别是对于那些直接通过IP地址访问的资源。I…

Java 将图片转base64和base64转图片

工具 Base64 和 图片互转。 导入的依赖 <!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl --><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-impl</artifactId><version>4.0.5</versi…

【linux】进程间通信(IPC)——匿名管道,命名管道与System V内核方案的共享内存,以及消息队列和信号量的原理概述

目录 ✈必备知识 进程间通信概述 &#x1f525;概述 &#x1f525;必要性 &#x1f525;原理 管道概述 &#x1f525;管道的本质 &#x1f525;管道的相关特性 &#x1f525;管道的同步与互斥机制 匿名管道 &#x1f525;系统调用接口介绍 &#x1f525;内核原理 …

【开发环境】搭建PX4+ROS2+MAVROS2+Simulink+Optitrack实物联合仿真环境

搭建PX4ROS2MAVROS2SimulinkOptiTrack实物联合仿真环境 Ubuntu中的安装过程下载并编译PX4固件代码安装ROS2安装VRPN动捕数据转换ROS2话题库安装VRPN库拉取vrpn_client_ros2节点代码并配置VRPN server参数编译软件包启动vrpn_client_ros2节点重命名话题名 /vrpn/fly/pose 为 /ma…

Mac VSCode 突然闪退、崩溃、打不开了

vscode 1.90.2版本下载&#xff0c;刚上传还在审核中 1、 思路历程 VSCode 作为前端常用开发工具&#xff0c;其重要性就不一一描述了。 所以 VSCode 突然打不开了&#xff0c;真的是让我一脸懵逼。 本来以为问题不大&#xff0c;于是 &#xff1a; 1、重启了一下VSCode 2、…

Python 爬虫:使用打码平台来识别各种验证码:

本课程使用的是 超级鹰 打码平台&#xff0c; 没有账户的请自行注册&#xff01; 超级鹰验证码识别-专业的验证码云端识别服务,让验证码识别更快速、更准确、更强大 使用打码平台来攻破验证码难题&#xff0c; 是很简单容易的&#xff0c; 但是要钱&#xff01; 案例代码及测…

记录些Redis题集(1)

Redis内存淘汰触发条件的相关配置如下&#xff1a; Redis通过配置项maxmemory来设定其允许使用的最大内存容量。当Redis实际占用的内存达到这一阈值时&#xff0c;将触发内存淘汰机制&#xff0c;开始删除部分数据以释放内存空间&#xff0c;防止服务因内存溢出而异常。 Redi…

vitest 单元测试应用与配置

vitest 应用与配置 一、简介 Vitest 旨在将自己定位为 Vite 项目的首选测试框架&#xff0c;即使对于不使用 Vite 的项目也是一个可靠的替代方案。它本身也兼容一些Jest的API用法。 二、安装vitest // npm npm install -D vitest // yarn yarn add -D vitest // pnpm pnpm …

【Linux】vim详解

1.什么是vi/vim? 简单来说&#xff0c;vi是老式的文本编辑器&#xff0c;不过功能已经很齐全了&#xff0c;但是还是有可以进步的地方。vim则可以说是程序开发者的一项很好用的工具&#xff0c;就连 vim的官方网站&#xff08; http://www.vim.org&#xff09;自己也说vim是一…

【公益案例展】华为云X《无尽攀登》——攀登不停,向上而行

‍ 华为云公益案例 本项目案例由华为云投递并参与数据猿与上海大数据联盟联合推出的 #榜样的力量# 《2024中国数据智能产业最具社会责任感企业》榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 夏伯渝&#xff0c;中国无腿登珠峰第一人&#xff0c;一生43年…

语言模型演进:从NLP到LLM的跨越之旅

在人工智能的浩瀚宇宙中&#xff0c;自然语言处理&#xff08;NLP&#xff09;一直是一个充满挑战和机遇的领域。随着技术的发展&#xff0c;我们见证了从传统规则到统计机器学习&#xff0c;再到深度学习和预训练模型的演进。如今&#xff0c;我们站在了大型语言模型&#xff…

免费开源数字人生成工具

使用步骤更是简单到不行&#xff1a; 1. 输入图片&#xff1a;选择你想要生成动态视频的肖像图片。 2. 输入音频&#xff1a;提供与图片匹配的音频文件&#xff0c;EchoMimic会根据音频内容驱动肖像的动态效果。 3. 设置参数&#xff1a;一般保持默认设置即可&#xff0c;当然&…

端到端自动驾驶系列(一):自动驾驶综述解析

端到端自动驾驶系列(一)&#xff1a;自动驾驶综述解析 End-to-end-Autonomous-Driving Abstract Abstract—The autonomous driving community has witnessed a rapid growth in approaches that embrace an end-to-end algorithm framework, utilizing raw sensor input to …