垃圾回收算法你不知道的奥秘

server/2025/1/9 12:47:34/

一、对象回收判定方法
1.引用计数法(PHP语言在用):快,方便,实现简单,缺点:对象相互引用时,很难判断对象是否该回收。
2.可达性分析(Java语言在用)
通过一系列的称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,可以被回收。
能作为GC Roots的对象包括下面几种:
1)    方法区中常量引用的对象。
2)    方法区中类静态属性引用的对象。
3)    虚拟机栈(栈帧中的本地变量表)中引用的对象。
4)    本地方法栈中JNI(即Native方法)引用的对象。

二、垃圾回收算法分类
1.Serial/Serial Old
最古老的,单线程,独占式,成熟,适合单CPU 服务器。

2.ParNew 
和Serial基本没区别,唯一的区别:多线程,多CPU的,停顿时间比Serial少。
ParNew垃圾收集器是Serial收集器的多线程版本。

3.Parallel Scavenge
吞吐量优先收集器。     新生代,复制算法。     并行的多线程收集器。    类似ParNew,更加关注吞吐量,达到一个可控制的吞吐量。    Server级别多CPU机器上的默认GC方式,主要适合后台运算不需要太多交互的任务。

4.Parallel Old
老年代,标记整理算法。     并行的多线程收集器。     
是Parallel Scavenge收集器的老年代版本,为了配合Parallel Scavenge的面向吞吐量的特性而开发的对应组合。    
在注重吞吐量以及CPU资源敏感的场合采用 。

5.CMS
用于老年代,标记清除算法。     并行与并发收集器。     
尽可能的缩短垃圾收集时用户线程停止时间。缺点在于: 
1)内存碎片 。
2)需要更多cpu资源 。
3)浮动垃圾问题,需要更大的堆空间 。    用于重视服务的响应速度、系统停顿时间和用户体验的互联网网站或者B/S系统。互联网后端目前CMS是主流的垃圾回收器。

6.G1
跨新生代和老年代。标记整理 + 化整为零 。    并行与并发收集器 。    JDK1.7才正式引入,采用分区回收的思维,基本不牺牲吞吐量的前提下完成低停顿的内存回收。可预测的停顿是其最大的优势。     面向服务端应用的垃圾回收器,目标为取代CMS。

并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop The World停顿的时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。

分代收集:与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。

空间整合:与CMS的"标记—清理"算法不同,G1从整体来看是基于"标记—整理"算法实现的收集器,从局部(两个Region之间)上来看是基于"复制"算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。

内存布局:在G1之前的其他收集器进行收集的范围都是整个新生代或者老年代,而G1不再是这样。使用G1收集器时,Java堆的内存布局就与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。
1)    新生代GC
回收Eden区和Survivor区,回收后,所有Eden区被清空,存在一个Survivor区保存了部分数据。老年代区域会增多,因为部分新生代的对象会晋升到老年代。
2)    并发标记周期 
初始标记:短暂,仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,产生一个全局停顿,都伴随有一次新生代的GC。
根区域扫描:扫描Survivor区可以直接到达的老年代区域。
并发标记阶段:扫描和查找整个堆的存活对象,并标记。
重新标记:会产生全局停顿,对并发标记阶段的结果进行修正。
独占清理:会产生全局停顿,对GC回收比例进行排序,供混合收集阶段使用。
并发清理:识别并清理完全空闲的区域,并发进行。
3)    混合收集 
对含有垃圾比例较高的Region进行回收。
G1当出现内存不足的的情况,也可能进行的Full GC回收。

G1中重要的参数:
-XX:MaxGCPauseMillis 指定目标的最大停顿时间,G1尝试调整新生代和老年代的比例,堆大小,晋升年龄来达到这个目标时间。
-XX:ParallelGCThreads:设置GC的工作线程数量。

7.未来的垃圾回收器ZGC(Z Garbage Collector)
ZGC通过技术手段把stw(Stop The World)的情况控制在仅有一次,就是第一次的初始标记才会发生,这样也就不难理解为什么GC停顿时间不随着堆增大而上升了,再大也是通过并发的时间去回收了。
关键技术:
1)    有色指针(Colored Pointers)
2)    加载屏障(Load Barrier)
存储在对象字段中的对象引用被实现为有色指针。存储在 JVM 堆栈中的对象引用在硬件堆栈或 CPU 寄存器中实现为无色指针。读屏障和存储屏障控制有色指针和无色指针之间的转换。

三、垃圾回收算法配置
-XX:+UseSerialGC 新生代和老年代都用串行收集器。
-XX:+UseParNewGC 新生代使用ParNew,老年代使用Serial Old。
-XX:+UseParallelGC 新生代使用Paraller Scavenge GC,老年代使用Serial Old。
-XX:+UseConcMarkSweepGC  新生代使用ParNew,老年代的用CMS。
-XX:+UseG1GC    使用G1垃圾回收算法
 


微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是程序员小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

欢迎关注。助您在编程路上越走越好!


http://www.ppmy.cn/server/30401.html

相关文章

【c语言实现内核链表】

在C语言中实现内核链表可以参考以下步骤: 定义链表节点结构:创建一个表示链表节点的结构体,通常包含一个数据成员和一个指向下一个节点的指针。 struct ListNode {// 数据成员int data;// 指向下一个节点的指针struct ListNode* next; };初…

ASP.NET Core日志管理(Serilog)

.net 6 web api项目添加日志(Serilog)管理,将日志输出到控制台、文件、数据库 Nuget安装:Serilog.AspNetCore 1、用于日志输出到控制台Serilog.Formatting.Compact 2、用于日志输出到SQLServer数据库Serilog.Sinks.MSSqlServer 3、用于日志输出到文件Serilog.Sinks.RollingF…

Flink checkpoint 源码分析- Checkpoint barrier 传递源码分析

背景 在上一篇的博客里,大致介绍了flink checkpoint中的触发的大体流程,现在介绍一下触发之后下游的算子是如何做snapshot。 上一篇的文章: Flink checkpoint 源码分析- Flink Checkpoint 触发流程分析-CSDN博客 代码分析 1. 在SubtaskCheckpointCoo…

vue3 element-plus 让el-container占满屏幕

在刚开始用element-plus的布局时&#xff0c;发现无法占满屏幕&#xff1a; 在App.vue中添加如下css代码&#xff1a; <style>html, body, #app {margin: 0;padding: 0;height: 100%;} </style>同时布局代码所在的component如下所示&#xff1a; <template&g…

opencv t函数

在OpenCV中&#xff0c;t函数通常用于转置矩阵&#xff08;Transpose&#xff09;。这意味着矩阵的行和列互换位置。 在C中&#xff0c;使用OpenCV库进行矩阵转置的代码如下所示&#xff1a; #include <opencv2/opencv.hpp> #include <iostream>int main() {// 创…

boost::asio::ip::tcp::socket set_option

Boost asio 官方教程简介_asio::write-CSDN博客 boost::asio::ip::tcp::socket 是一个用于异步I/O操作的类&#xff0c;它是Boost.Asio库的一部分&#xff0c;专门用于处理TCP套接字。 以下是一个简单的使用 boost::asio::ip::tcp::socket 的例子&#xff0c;这个例子展示了如…

238. 除自身以外数组的乘积/41. 缺失的第一个正数

238. 除自身以外数组的乘积 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&a…

Python中覆盖类属性最好的方法

Python中有一个很独特的功能,类属性可为实例属性提供默认值。下面Person类中有一个名为current_year的类属性。compute_age方法中用到了这个属性,而且都故意使用self.current_year读取它的值。因为Person本身没有current_year这个实例属性,所以self.current_year默认获取的是…