当前位置: 首页 > news >正文

Java 垃圾回收

文章目录

  • 1 Java 垃圾回收
    • 1.1 JVM
    • 1.2 Java 对象生命周期
  • 2 如何判断一个对象可被回收
    • 2.1 引用计数算法
    • 2.2 可达性分析算法
  • 3 垃圾回收过程
    • 3.1 总体过程
    • 3.2 为什么要进行世代垃圾回收?
    • 3.3 分代垃圾回收过程

在 C 和 C++ 中,许多对象要求程序员声明他们后为其分配资源,然后才能安全地使用对象。使用完后,则需要程序员将这些资源释放到自由内存池。如果资源得不到释放,则认为代码泄露内存。然而,如果过早地释放,又可能发生数据丢失、Null指针等问题。

Java 和 C# 都有单独的管理应用程序管理对象的生存期并进行垃圾回收 (Garbage Collection - GC) ,这样程序员可以不再关心内存释放问题,保证系统的性能和稳定性。

这里记录 Java 垃圾回收相关知识点,后面会再记录 C# 垃圾回收。

部分借鉴网络一些总结文章

1 Java 垃圾回收

Java 中,JVM 通过跟踪已经分配资源的引用来释放不再使用的堆存。只要 JVM 检测到对象不再被引用,垃圾回收器就会在适当的时候回收对象。

1.1 JVM

下载 Java 的时候,我们会得到 JRE (Java Runtime Environment),JRE 中包括了 JVM (Java Virtual Machine) 和 类库 (Java platform core classesJava platform libraries)。

Java 语言的一个重要特点就是与平台无关,即得益于 JVM 的引入,Java在不同平台上运行时不需要重新编译,秩序生成在 JVM 上运行的目标代码,就可以多平台运行。
在这里插入图片描述

JVM 定义了程序执行期间是用的数据区域,如程序计数器、堆、栈、方法区、运行时常量池等。这些数据区域中的一些在JVM启动时创建,JVM退出时销毁。

1.2 Java 对象生命周期

Java 中,对象的生命周期包括:
在这里插入图片描述

public class ObjectLifecycle {public static void main(String[] args) {ObjectLifecycle obj = new ObjectLifecycle();  // 创建阶段// 使用阶段obj = null;  // 不可达阶段System.gc();  // 触发垃圾回收,进入回收阶段}@Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println("垃圾回收前调用finalize方法");}
}

2 如何判断一个对象可被回收

2.1 引用计数算法

给对象添加一个引用计数器,对象每增加一个引用,计数器加1,引用失效计数器减1,引用计数为0的对象可以被回收。

假如两个对象互相引用,那么引用计数器永远不会为0,导致对象无法回收,因此 JVM 不再使用引用计数算法:

public class ReferenceCountingGC {public Object instance = null;public static void main(String[] args) {ReferenceCountingGC objectA = new ReferenceCountingGC();ReferenceCountingGC objectB = new ReferenceCountingGC();objectA.instance = objectB;objectB.instance = objectA;}
}

2.2 可达性分析算法

通过 GC Roots 作为起始点进行搜索,所有不可达的对象即为可被回收的对象。
在这里插入图片描述
Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC Roots 一般包含以下内容:

在虚拟机栈(栈帧中的本地变量表)中引用的对象:

Java public void method() { Object localVariable = new Object(); // localVariable是GC Roots }

在方法区中类静态属性引用的对象:

Java public class MyClass { private static Object staticObject = new Object(); // staticObject是GC Roots }

在方法区中常量引用的对象:

Java public class MyClass { private static final String CONSTANT_STRING = “constant”; // CONSTANT_STRING是GC Roots }

在本地方法栈中JNI(即通常所说的Native方法)引用的对象:

Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。

所有被同步锁(synchronized关键字)持有的对象:

Javapublic synchronized void synchronizedMethod() { // 当前对象(this)在执行同步方法时是GC Roots }

所有被同步锁(synchronized关键字)持有的对象:

3 垃圾回收过程

3.1 总体过程

Step1. 标记 (Marking)
GC 在这个阶段辨别内存是否被使用,被引用的对象这里展示为蓝色,没有被引用的为橙色。这个过程效率不高
在这里插入图片描述

Step2: 标准清理 (Normal Deletion)
清理时,直接把可以回收的对象内存释放,留下被引用的对象和指向可用空间的指针。内存碎片会导致没有足够连续的空间给大对象分配内存
在这里插入图片描述
Step3: 压缩清理 (Deletion with Compacting)

通过把被引用的对象都移动到一起,后续为新对象分配内存则会更加容易和快速。
在这里插入图片描述

3.2 为什么要进行世代垃圾回收?

如上所述,标记和压缩 JVM 中所有对象是相当低效的,随着分配的对象越来越多,对象表越来越到,导致垃圾回收时间越来越长。同时,又有大量实证表明,大多数对象生命都是短暂的。

下面是数据示例图,Y周显示分配的字节数存活时间,X是随着时间推移分配的字节数。

即随着时间推移,分配的对象越来越少对。
在这里插入图片描述
因此,从对象分配的行为中,为了提高JVM 性能,堆被分为了更小的部分(或成为代),分别是:新生代(Young Gneration)、老年代 (Old Generation) 和 永久代(Permanent Generation).
在这里插入图片描述
新生代:新对象首先被分配到这里,当年轻代内存用尽,会触发一次 minor garbage colletion。如果对象的死亡率高,那么这次 minor garbage collection 则会有效的优化内存。新生代会被分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用一块 Eden 和一块 Survivor。回收时,会将 Eden 和 Survivor 中还存活得对象复制到另一块 Survivor空间中,最后清理 Eden 和使用过的那一块 Survivor。

这个过程会快速地完成,当另一块 Survivor不足以存放 Eden 和 Survivor 存活对象时,所有幸存对象 (surviving objects) 会被标记年龄并移动到 old generation

Minor GC - Stop the world EventMinor GCStop the world 的行为,即所有的应用县城都要停止,直到整个操作完成。

老年代: 一般来说,新生代对象的age达到一定的阈值,就会被移动到老年代,而老年代的回收称为 major garbage collection

Major GC - Stop the world Event: Major GC 也是 Stop the world 的行为,通常会更慢一些,所以对于响应式应用程序,应该尽量减少这类GC,由于 Java 虚拟机提供了多种垃圾回收器,这个GC的长度受垃圾回收器所影响。

永久代: 这里面包括了 JVM 描述应用进程中是用的类和方法所需要的静态文件。永久代也被称为方法区,方法区的回收内容主要是 废弃常量和无用的类。

3.3 分代垃圾回收过程

上面我们理解了为什么要分代回收和回收的基本操作,下面展示具体回收过程:

1. 一个新的对象分配内存并记录在 Eden 区域 在这里插入图片描述
2. 当 Eden 区域占满,触发一次 minor GC
在这里插入图片描述
3. 被引用对象移动到第一块 Survivor 区域(S0),没有被引用的对象则被删除
在这里插入图片描述
4. 在下一次 Minor GC,类似上一步没有被引用的对象被释放,Eden 和 引用对象则会被一起移动到第二块 Survivor 区域(S1),移动后,EdenS0 被清空,可以看到现在 S1 区域有不同age的对象。
在这里插入图片描述

5. 下次 Minor GC,同样的流程重复。但是这次 S0S1 互换。引用的对象会被移动到 S0,幸存的对象 age 继续增加,EdenS1 都被清空。
在这里插入图片描述
6. 经过几次 Minor GC 之后,对象age达到阈值(这里为8),他们就会被移动到老年代
在这里插入图片描述
7.随着Minor GC 不停地进行,幸存的对象持续promote到老年代
在这里插入图片描述
8. 随着老年代 的对象不断增多,最终会触发 Major GC 来释放更多的内存空间。
在这里插入图片描述

相关文章:

Java 垃圾回收

文章目录 1 Java 垃圾回收1.1 JVM1.2 Java 对象生命周期 2 如何判断一个对象可被回收2.1 引用计数算法2.2 可达性分析算法 3 垃圾回收过程3.1 总体过程3.2 为什么要进行世代垃圾回收?3.3 分代垃圾回收过程 在 C 和 C 中,许多对象要求程序员声明他们后为其…...

多客陪玩系统-开源陪玩系统平台源码-支持游戏线上陪玩家政线下预约等多场景应用支持H5+小程序+APP

多客陪玩系统-开源陪玩系统平台源码-支持游戏线上陪玩家政按摩线下预约等多场景应用支持H5小程序APP 软件架构 前端:Uniapp-vue2.0 后端:Thinkphp6 前后端分离 前端支持: H5小程序双端APP(安卓苹果) 安装教程 【商业…...

书生·浦语大模型全链路开源体系-笔记作业2

全部写成了shell脚本,可以一键执行。 笔记: 1. 环境安装(InternStudio开发机) # 1. 创建conda环境 studio-conda -o internlm-base -t demo # 2. 激活conda环境 conda activate demo # 3. 安装额外的依赖 pip install huggingface-hub0.17.3 pip inst…...

手把手教你发布你的第一个npm插件包

在开源的世界里,npm(Node Package Manager)不仅是JavaScript生态中不可或缺的一部分,也是全球最大的软件注册表,它使得分享和复用代码变得异常简单。如果你有一个很棒的想法或者实用的功能想要封装成一个npm包供他人使…...

Docker-compose 编排lnmp(dockerfile) 完成Wordpress

一、部署 Nginx 镜像 1. 建立工作目录 mkdir /opt/lnmp/nginx -pcd /opt/lnmp/nginx#上传 nginx 安装包 nginx-1.12.0.tar.gz#上传 wordpress 服务包 wordpress-4.9.4-zh_CN.tar.gz mkdir /opt/lnmp/nginx/htmltar zxvf wordpress-4.9.4-zh_CN.tar.gz -C /opt/lnmp/nginx/html…...

秋招突击——算法打卡——5/28——复习{Z字形变换、两数之和}——新做:{整数反转、字符串转整数}

文章目录 复习Z字形变换实现代码参考代码 两数之和复习代码 新作整数反转个人实现实现代码 参考做法字符串转换整数个人解法 分析总结 复习 Z字形变换 实现代码 这里使用了他的思想,但是没有用他的代码,虽然已经比上次简洁了,但是还是不够&…...

PPT设置为本框的默认格式以及固定文本框

调整文本框固定位置 双击文本框之后勾选如下三个位置 设置文本框为默认 在调整好文本框的基本性质后,设置为默认即可...

计算机基础(5)——进制与进制转换

💗计算机基础系列文章💗 👉🍀计算机基础(1)——计算机的发展史🍀👉🍀计算机基础(2)——冯诺依曼体系结构🍀👉&#x1f34…...

发现情绪背后的真实心理需求,选择适合你的情绪调节方式

一、教程描述 心态对人的生活质量以及身体健康等多方面,都会产生非常重要的影响,受到不良情绪的影响,人的心态也会发生一定的变化。对于处于不良情绪状态的人来讲,应该重视学会调整自己的情绪。在心理学上,人的每种情…...

代理记账公司的五大问题及其解决方案

代理记账公司是现代企业管理中不可或缺的一部分,它为企业的日常运营提供了专业、高效的服务,随着行业的发展和竞争的加剧,代理记账公司的面临的问题也日益突出,这些问题主要表现在以下几个方面: 业务流程不规范 许多代…...

TH方程学习 (7)

一、内容介绍 TH存在广泛应用,在下面案例中,将介绍几种相对运动模型,斜滑接近模型,本节学习斜滑接近制导方法能够对接近时间、接近方向以及自主接近过程的相对速度进行控制。施加脉冲时刻追踪器的位置连线可构成一条直线&#xf…...

2024最新python入门教程|python安装|pycharm安装

前言:在安装PyCharm之前,首先需要明确PyCharm是一款功能强大的Python集成开发环境(IDE),由JetBrains公司开发。PyCharm旨在通过提供智能代码补全、语法高亮、代码检查、快速导航和重构等丰富的编码辅助工具&#xff0c…...

docker架构

docker架构 Docker daemon 是Docker最核心的后台进程,它负责响应来自Dockerclient的请求,然后将这此请求翻译成系统调用完成容器管理操作。该进程会在后台后启动一个APIServer,负责接收由 Dockerclient发送的请求;接收到的请求将通…...

使用Java进行网络采集:代理IP与参数传递详解

在Java编程语言中,参数传递机制是一个常见的讨论话题。理解这一点对于编写高效且无错误的Java代码至关重要。本文将探讨Java的参数传递机制,解析其究竟是“按引用传递”还是“按值传递”,并结合网络爬虫技术的实例,展示如何在实际…...

多功能光时域反射仪的工作原理

6426A-2101多功能光时域反射仪是新一代掌上型智能化光纤通信测量仪器,具有强大的功能和广泛的应用领域。它能够显示光纤及光缆的损耗分布曲线图,测量光纤及光缆的多种关键参数,包括长度、损耗、接续质量等,为光纤通信系统的工程施…...

目标检测数据集 - 海洋垃圾检测数据集下载「包含VOC、COCO、YOLO三种格式」

数据集介绍:海洋垃圾检测数据集,真实拍摄海洋海底场景高质量垃圾检测图片数据,涉及场景丰富,比如海底塑料垃圾数据、海底铁制品罐状垃圾数据、海底纸张垃圾数据、海洋生物和海底垃圾同框数据、海底探索仪器和海底垃圾同框数据、海…...

如何进行Java程序的性能优化

在软件开发中,性能优化是一个至关重要的环节,它直接影响到用户体验、系统稳定性和资源消耗。对于Java程序而言,性能优化更是不可或缺的一部分。下面,我将从技术难点、面试官关注点、回答吸引力和代码举例四个方面,详细…...

Echarts柱状图数据太多,自定义长度之后,自适应浏览器缩放

不知道是不是最优解,但是当前解决了我遇到的问题,如有更好的方法,希望看到这篇文章的同学可以不吝指导一番,非常感谢 1、问题描述: 因Ecahrts柱状图数据有时多有时少,所以在数据达到一定程度之后&#xff…...

小白级教程—安装Ubuntu 20.04 LTS服务器

下载 本教程将使用20.04版进行教学 由于官方速度可能有点慢,可以下方的使用清华镜像下载 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/ 点击20.24版本 选择 ubuntu-20.04.6-live-server-amd64.iso 新建虚拟机 下载好后 我们使用 VMware 打开它 这里选…...

9、中华人民共和国个人信息保护法

第一章 总  则 第一条 为了保护个人信息权益,规范个人信息处理活动,促进个人信息合理利用,根据宪法,制定本法。 第二条 自然人的个人信息受法律保护,任何组织、个人不得侵害自然人的个人信息权益。 第三条 在中华人民共和国境内处理自然人个人信息的活动,适用本…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...