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 classes, Java 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 Event:Minor GC 是 Stop 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),移动后,Eden 和 S0 被清空,可以看到现在 S1 区域有不同age的对象。

5. 下次 Minor GC,同样的流程重复。但是这次 S0 和 S1 互换。引用的对象会被移动到 S0,幸存的对象 age 继续增加,Eden 和 S1 都被清空。

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)——冯诺依曼体系结构🍀👉ἴ…...
发现情绪背后的真实心理需求,选择适合你的情绪调节方式
一、教程描述 心态对人的生活质量以及身体健康等多方面,都会产生非常重要的影响,受到不良情绪的影响,人的心态也会发生一定的变化。对于处于不良情绪状态的人来讲,应该重视学会调整自己的情绪。在心理学上,人的每种情…...
代理记账公司的五大问题及其解决方案
代理记账公司是现代企业管理中不可或缺的一部分,它为企业的日常运营提供了专业、高效的服务,随着行业的发展和竞争的加剧,代理记账公司的面临的问题也日益突出,这些问题主要表现在以下几个方面: 业务流程不规范 许多代…...
TH方程学习 (7)
一、内容介绍 TH存在广泛应用,在下面案例中,将介绍几种相对运动模型,斜滑接近模型,本节学习斜滑接近制导方法能够对接近时间、接近方向以及自主接近过程的相对速度进行控制。施加脉冲时刻追踪器的位置连线可构成一条直线…...
2024最新python入门教程|python安装|pycharm安装
前言:在安装PyCharm之前,首先需要明确PyCharm是一款功能强大的Python集成开发环境(IDE),由JetBrains公司开发。PyCharm旨在通过提供智能代码补全、语法高亮、代码检查、快速导航和重构等丰富的编码辅助工具,…...
docker架构
docker架构 Docker daemon 是Docker最核心的后台进程,它负责响应来自Dockerclient的请求,然后将这此请求翻译成系统调用完成容器管理操作。该进程会在后台后启动一个APIServer,负责接收由 Dockerclient发送的请求;接收到的请求将通…...
使用Java进行网络采集:代理IP与参数传递详解
在Java编程语言中,参数传递机制是一个常见的讨论话题。理解这一点对于编写高效且无错误的Java代码至关重要。本文将探讨Java的参数传递机制,解析其究竟是“按引用传递”还是“按值传递”,并结合网络爬虫技术的实例,展示如何在实际…...
多功能光时域反射仪的工作原理
6426A-2101多功能光时域反射仪是新一代掌上型智能化光纤通信测量仪器,具有强大的功能和广泛的应用领域。它能够显示光纤及光缆的损耗分布曲线图,测量光纤及光缆的多种关键参数,包括长度、损耗、接续质量等,为光纤通信系统的工程施…...
目标检测数据集 - 海洋垃圾检测数据集下载「包含VOC、COCO、YOLO三种格式」
数据集介绍:海洋垃圾检测数据集,真实拍摄海洋海底场景高质量垃圾检测图片数据,涉及场景丰富,比如海底塑料垃圾数据、海底铁制品罐状垃圾数据、海底纸张垃圾数据、海洋生物和海底垃圾同框数据、海底探索仪器和海底垃圾同框数据、海…...
如何进行Java程序的性能优化
在软件开发中,性能优化是一个至关重要的环节,它直接影响到用户体验、系统稳定性和资源消耗。对于Java程序而言,性能优化更是不可或缺的一部分。下面,我将从技术难点、面试官关注点、回答吸引力和代码举例四个方面,详细…...
Echarts柱状图数据太多,自定义长度之后,自适应浏览器缩放
不知道是不是最优解,但是当前解决了我遇到的问题,如有更好的方法,希望看到这篇文章的同学可以不吝指导一番,非常感谢 1、问题描述: 因Ecahrts柱状图数据有时多有时少,所以在数据达到一定程度之后ÿ…...
小白级教程—安装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、中华人民共和国个人信息保护法
第一章 总 则 第一条 为了保护个人信息权益,规范个人信息处理活动,促进个人信息合理利用,根据宪法,制定本法。 第二条 自然人的个人信息受法律保护,任何组织、个人不得侵害自然人的个人信息权益。 第三条 在中华人民共和国境内处理自然人个人信息的活动,适用本…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
