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 来释放更多的内存空间。
在这里插入图片描述

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

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

相关文章

【第三节】C/C++数据结构之栈与队列

目录 一、数据结构-栈 1.1 栈的定义 1.2 栈的 ADT (Abstract Data Type) 1.3 栈的顺序存储结构及实现 二、数据结构-队列 2.1 队列的定义 2.2 队列的 ADT 2.3 队列的顺序存储结构与实现 2.4 优先队列 2.5 各种队列异同点 一、数据结构-栈 1.1 栈的定义 栈(Stack)可…

Web3设计风格和APP设计风格

Web3设计风格和传统APP设计风格在视觉和交互设计上有一些显著的区别。这些差异主要源于Web3技术和理念的独特性,以及它们在用户体验和界面设计中的具体应用。以下是Web3设计风格与传统APP设计风格的主要区别。北京木奇移动技术有限公司,专业的软件外包开…

CSS(盒子模型,定位,浮动,扩展)

CSS 盒子模型:外边距:内边距:水平居中: 定位:相对定位:绝对定位:固定定位: 浮动:扩展: 盒子模型: 盒子模型(Box Model) 规定了元素框处理元素内容…

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

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

恢复最近删除的照片!3个终极指南大揭秘!

亲爱的朋友们,你们有没有过这样的经历:一时手滑,不小心删除了手机里的重要照片,然后瞬间感觉自己的世界都要崩塌了?别担心,今天我就来给大家分享一下如何找回最近删除的照片,并介绍详细的方法和…

详解Spring MVC

目录 1.什么是Spring Web MVC MVC定义 2.学习Spring MVC 建立连接 RequestMapping 注解介绍及使用 获取单个参数 获取多个参数 获取普通对象 获取JSON对象 获取基础URL参数 获取上传文件 获取Header 获取Cookie 获取Session 总结 1.什么是Spring Web MVC 官⽅对于…

AI 正在攻克难题——赋予计算机嗅觉

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

MySQL 自定义函数(实验报告)

一、实验名称: 自定义函数 二、实验日期: 2024年 6 月 1 日 三、实验目的: 掌握MySQL自定义函数的创建及调用; 四、实验用的仪器和材料: 硬件:PC电脑一台; 配置:内存&#…

OpenCV学习 基础图像操作(十七):泛洪与分水岭算法

原理 泛洪填充算法和分水岭算法是图像处理中的两种重要算法,主要用于区域分割,但它们的原理和应用场景有所不同,但是他们的基础思想都是基于区域迭代实现的区域之间的划分。 泛洪算法 泛洪填充算法(Flood Fill)是一…

中电金信:从规划到落地,中电金信全程陪伴式服务助力泛金融数字化转型

在当前的全球经济和金融发展格局中,金融行业正经历着一场以数字化为核心的快速转型。中国银行业和保险业已经成功探索出一条数字化转型的路径,并积累了丰富的实践经验。然而,泛金融领域则仍处于数字化转型的初期阶段,其转型能力因…

【案例实战】 基于OpenCV实现鹿茸面积计算

学习《人工智能应用软件开发》,学会所有OpenCV技能就这么简单! 做真正的OpenCV开发者,从入门到入职,一步到位! 有人在我得B站答疑群里发了下面的图: 问:如何计算鹿茸最外圈蜡皮面积占整个鹿茸…

AI 入门指南二 :AI提示词(Prompt)

一,提示词的定义 提示词在中文中意为“触发”,在自然语言处理(NLP)的领域,它更接近于一个“心领神会”的概念,而非具有明确定义的术语。 简而言之,提示词是用户对大型语言模型的输入&#xff0…

Centos 7部署NTP

介绍 NTP是Network Time Protocol(网络时间协议)的简称,它是用来通过互联网或局域网将计算机时钟同步到世界协调时间(UTC)的协议。 安装 # yum安装 yum install -y ntp# 离线安装 #下载地址:https://mir…

全球首款AR电脑上线,可投影100英寸屏幕

近日,Sightful公司推出了一款名为Spacetop G1的革命性笔记本电脑,将AR技术与传统笔记本电脑巧妙融合,打造出令人惊叹的全新办公体验。 全球首款AR电脑上线,可投影100英寸屏幕 不同于传统笔记本电脑依赖物理屏幕显示内容&#xff0…

新手如何正确使用代理IP,一篇文章学会,包含实战案例

前言 一、代理IP1.1 什么是代理IP?1.2 代理ip分类1.3 代理IP的作用和优势 二、更换代理IP的方法2.1 重启路由器或光猫2.2 用拨号 vps 重拨更换动态IP代理。2.3 使用浏览器更换IP 三、IPIDEA代理的优势四、提取代理IP4.1 提取步骤4.2 浏览器使用代理IP 五、使用代理I…

c#基础()

学习目标 了解:嵌套类,匿名类,对象初始化器 重点:类的定义以及对象,构造方法,this和static关键字 掌握:面向对象的概念,访问修饰符,垃圾回收 面向对象 面向对象的概…

微信小程序毕业设计-在线订餐系统项目开发实战(附源码+论文)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:微信小程序毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计…

Flink系列一:flink光速入门 (^_^)

引入 spark和flink的区别:在上一个spark专栏中我们了解了spark对数据的处理方式,在 Spark 生态体系中,对于批处理和流处理采用了不同的技术框架,批处理由 Spark-core,SparkSQL 实现,流处理由 Spark Streaming 实现&am…

期刊的分类与级别

在学术界,期刊的分类与级别构成了一个评价学术成果和学者贡献的重要标准,同时也是学术出版与学术交流的基础。然而,对于初涉学者来说,理解期刊的分类与级别可能并不直观。本文旨在提供一个系统性的解释,并阐述为何期刊…

云南区块链商户平台发票助手成品

目录 1 概述2 功能对比3 项目演示图4 核心逻辑4.1智能赋码4.2 解密方法4.3 登录与检测4.4 发票金额大写转换4.5 检查登录是否失效4.6 验证码识别5 演示效果6 项目部署6.1 Web站点部署6.1.1 环境6.1.2 前端6.1.3 后端6.2 Docker部署6.2.1 构建镜像6.2.2 创建容器6.3.3 访问项目域…