GC机制小结

本文深入探讨了垃圾收集机制的重要性及其实现方式,包括如何判断对象是否成为垃圾、不同类型的垃圾收集器及其工作原理,比如引用计数收集器、跟踪收集器等,并介绍了处理堆碎片的方法和技术,如压缩收集器、拷贝收集器以及按代收集的收集器。

1.为什么要使用垃圾收集?

 

   字面是说是“垃圾收集”,更精确点就是“内存回收”,在一个对象不再被程序引用时,它所占用的堆空间就可以回收,以便分配给新对象使用。而且除了释放不再被引用的对象外,垃

圾收集器还要处理堆碎块(堆碎块是在正常的程序运行时产生的),因为新的对象分配了空间,不再被引用的对象被释放,所以堆内存的空闲位置介于活对的对象之间,而请求分配新对象时可能不得不增大堆空间,因为虽然总的空闲空间是够的,但堆中没有连续的空闲空间放得下新对象。

 

   上面是垃圾收集的作用,其好处在于:1)提高了工作效率,在一个没有垃圾收集机制的语言下编程,程序员还要花时间来解决难以捉摸的内存问题

                                                2)帮助程序保持完整性,因为程序员不可能因为失误错误地释放内存而导致jvm崩溃

 

2.垃圾收集器怎么知道对象不再被引用?

  

    垃圾检测通常是通过建立一个根对象的集合并且检查从这些根对象开始的可触及性来实现。可触及就是正在执行的程序可以访问到的根对象和某个对象之间存在引用路径。

    区分活动对象和垃圾的两个基本方法是引用计数跟踪。

 

3.引用计数收集器是怎么判定对象为垃圾的?

  

   引用计数的原理是:堆中第一个对象都有一个引用计数,当有一个对象被创建时,这个对象的引用计数被置为1。当有其他变量被赋值为这个对象的引用时,计数加1;当这个对象的引用超过了生存期或被设置为新的值,计数减1;当计数为0时,对象被认为是垃圾,将被回收;

   这种方法的早已过时,主要缺陷是:他无法检测出循环引用(即两个或多个对象互相引用),例如:父对象有一个对子对象的引用,子对象又反过来引用父对象,这时计数永远不可能为0。

 

4.跟踪收集器又是怎么一回事?

 

   跟踪就是对对象设置标记,通过一个从根结点开始的对象引用图追踪对象,在这个过程中对遇到的对象打上标记,当追踪结束时没有被打上标记的就是无法触及的,从而可以被回收。

 

5.怎么处理堆碎块?

 

   一般处理堆碎块有以下几种收集器:

  

   1.压缩收集器:把活动的对象都推到堆的一端,从而使另一端出瑞一个大的连续空闲区,所有被移动的对象的引用也被更新,指向新的位置;为了简便,更新被移动的对象引用时通过一个间接引用层,因为不直接引用堆中的对象而对象的引用实际上指向一个对象句柄表的话不用改变引用指向的位置,但损失了部分性能。

 

   2.拷贝收集器:把所有的活动的对象移动到一个新的区域,在这个过程中,活动对象被紧挨着布置从而消除原本它们在旧区域的空隙。一般的拷贝收集算法是——停止并拷贝,在这个方法中堆被分为两个区域,任何时候都只使用其的一个区域。对象在同一个区域分配,直到这个区域满了为止;这时程序中止,堆被遍历,遍历到的活动对象被拷贝到另外一个区域,完成后程序继续执行,如此循环;这种方法的代价是:对于指定大小的堆来说需两倍大小的内存。

下图是“停止并拷贝”算法的垃圾收集堆的图形描述:第一张图中,堆的下半部分没有被使用,上半部分被对象零散的填充;2图是上半部分逐渐被填充,3图中上半部分被填满,这时程序中止,垃圾收集器开始工作,从根结点开始追踪活动对象图,当遇到活动对象时就拷贝到堆的下半部分,每一个都紧挨着,如4图;如此打循环:

   3.按代收集的收集器

     简单的停止拷贝收集器的缺点在于:第一次收集,所有的活动对象都要被拷贝,而程序中一般都有以下特点:

     1)大多数程序创建的大部分对象都具有很短的生命期;

     2)大多数程序都创建一些具有非常长生命周期的对象;

     简单的停止拷贝收集器每次都把那些生命周期长的对象来回拷,浪费了时间;按代收集器通过把对象按照寿命来分组,更多的收集那些年幼的对象,当一个年幼对象经过几次收集后仍然存活,那就将它提升为寿命更高的一代,从而对这个对象的收集频率就减少了,帮命越长的收集频率就越小;

 

  4.自适应收集器:看这个收集器的名字,顾名思义:根据不同的情况选择不同的垃圾收集技术;

 

6.什么是火车算法

 

    由于垃圾收集时一般会停止程序,如果停止的时间长得让用户注意到而不满意,那就说明这种算法存在破坏性,为了减少这种破坏性而采用渐进式收集算法(每次回收一部分),通常渐进式收集器都是按代收集器,而火车算法就是为了在成熟空间空间(最高寿的那个年龄层)提供限定时间的渐进收集。

   火车算法把成熟对象空间划分为固定长度的内存块,算法每次在一个块中单独执行,每一个块属于一个集合,块就是“车厢”,集合就是“火车”,成熟对象空间就是“火车站”;就如车厢一样,块在一个集合中有序的;集合也被排序,就像火车站中的火车按轨道排列一样,如下图:

对象从更年轻的年龄层的子堆中进入成熟对象空间都会被附加到任何已存在的火车中或者为他们专门创建一列或多列火车。

     每一次执行火车算法的时候,它不是收集最小数字的火车中的最小数字车厢,就是收集整列最小数字的火车,算法首先检查指向最小数字火车中任何车厢的引用,如果不存在任何来自最小数字火车以外的引用指向它内部包含的对象,那么整个火车都是垃圾,回收整个火车;如果不都是垃圾,那么将注意力放在火车中最小数字车厢上,首先把所有被最小数字车厢外部的车厢引用的对象转移到其他车厢去,之后任何保留在车厢内的对象都是没有引用的,可以被回收;

而保证整列火车中没有循环的数据结构的关键是算法如何移动对象:

1)如果对象被成熟对象空间的其他火车引用,对象不被转移到引用它的那列火车中去;

2)然后转移过后的对象被扫描,查找对原车厢的引用,发现的任何被外用的对象都被转移到引用它的火车中去;

3)新被转移的对象也被扫描,这个过程不断重复,直到没有任何来自其他火车的引用指向正被收集的车厢;

4)如果接收对象的火车没有空间了,那么算法会创建新的车厢,并附加到那列火车的尾部;

 

7.终结

   java中一个对象可以拥有终结方法:这个方法是垃圾收集器在释放对象前必须运行的。这个方法使垃圾收集器要做的工作更加复杂,因为垃圾收集器必须检查它所发现的不再被引用的对象是否存在终结方法——finalize();还得记住一点:是垃圾收集器运行对象的终结方法。

 

8.GC中对象的六种可触及状态

   1.强可触及:对象可以从根结点不通过任何引用对象搜索到

   2.软可触及:对象不是强可触及的,但是可以从根结点开始通过一个或多个(未被清除的)软引用对象触及

   3.弱可触及:对象既不是强可触及也不是软可触及的,但是从根结点开始可以通过一个或多个弱引用对象触及

   4.可复活的:对象既不是强可触及、软可触及,也不是弱可触及,但是仍然可能通过执行某些终结方法复活到这几种状态之一

   5.影子可触及:不上以上任何可触及状态,也不能通过终结方法复活,并且它可以从根结点开始通过一个或多个影子引用对象触及(影子引用不会被垃圾收集器清除,由程序明确地清除

   6不可触及:就是已经准备回收的状态

 

 

 

 

 

<think> 我们正在讨论SSD垃圾回收机制的原理。用户已经提供了三个引用,我们需要根据这些引用来组织答案。 引用[1]提到:SSD在可用空间富裕时不需要做GC,因此速度快;当需要GC时速度会变慢。另外,用户数据的写入模式(顺序写 vs 随机写)会影响GC性能,顺序写产生的垃圾集中,利于回收,而随机写则相反。 引用[2]解释了GC的基本过程:复制有效数据到空白页,擦除整个块,然后新数据可以写入擦除后的块。 引用[3]则介绍了主动GC(后台GC):在空闲时检查剩余可用块,并在没有I/O操作时提前做GC,避免延时。 根据这些引用,我们可以将回答组织如下: 1. 为什么需要GC? -> 引用[2]说明删除文件只是在文件表中标记,无效数据仍占据空间,需要回收。 2. GC的基本过程 -> 引用[2]描述的步骤:复制有效数据、擦除块。 3. GC对性能的影响 -> 引用[1]提到的变慢原因以及写入模式的影响。 4. 主动GC(后台GC)-> 引用[3]所述的后台操作。 另外,我们之前回答中提到的GC原理(步骤1、2、3)也可以融入进去,但要以引用提供的资料为主。 注意:用户要求使用中文,数学公式用$...$或$$...$$,并生成相关问题。 因此,回答结构如下: 一、引言:简述GC的必要性(基于引用[2]) 二、GC的基本原理(结合引用[2]和之前的步骤) 三、GC如何执行:分为前台和后台(主动GC来自引用[3]) 四、影响GC效率的因素(引用[1]提到的写入模式) 五、小结 然后生成相关问题。 注意:引用标识要自然地加在引用内容的末尾。 </think> ### SSD垃圾回收(GC机制原理详解 #### 一、GC的必要性基础 SSD使用**NAND闪存**存储数据,其物理特性要求: 1. **数据不能就地更新**:修改数据时需写入新位置,原数据变为无效(但物理空间仍被占用)[^2] 2. **擦除操作以块为单位**: - 最小写入单元:页面(Page,通常4KB) - 最小擦除单元:块(Block,通常含64-256个页面) $$ \text{擦除开销} \propto \frac{\text{有效数据迁移量}}{\text{块大小}} $$ 当无效数据积累导致可用空间不足时,GC机制被触发以回收空间[^1]。 #### 二、GC核心工作流程 1. **识别回收目标** - SSD控制器通过**闪存转换层(FTL)** 追踪页面状态 - 优先选择**无效页面比例高**的块(如70%无效页面),最大化回收效益[^1] 2. **有效数据迁移** - 将目标块中的有效数据复制到**空闲块**的新页面 - 更新FTL映射表(逻辑地址→新物理地址) ```plaintext 示例:块A含50%有效页面 → 迁移至块B → 块A变为全无效 ``` 3. **块擦除与回收** - 整块擦除目标块(如块A) - 该块加入**空闲块池**供新数据写入[^2] #### 三、GC触发模式对比 | **模式** | **触发条件** | **优势** | **劣势** | |----------------|---------------------------|----------------------------|----------------------| | **主动GC** | SSD空闲时定期触发[^3] | 避免I/O延迟,维持稳定性能 | 依赖设备空闲时间 | | **被动GC** | 写入时空间不足强制触发 | 确保写入操作立刻完成 | 直接增加用户请求延迟 | > 优化策略:现代SSD动态混合两种模式,空闲时执行主动GC(后台任务),高负载时被动GC兜底[^3]。 #### 四、关键影响因素 1. **写入模式决定GC效率** - **顺序写入**:无效页面集中分布,GC只需迁移少量有效数据 $$ \text{GC效率} \propto \frac{1}{\text{有效数据比例}} $$ - **随机写入**:有效数据碎片化,GC需迁移更多页面,性能显著下降[^1] 2. **空间利用率与性能权衡** - 预留空间(OP, Over-Provisioning)越大 → GC频率越低 → 性能越好 - 典型OP配置:消费级7-28%,企业级≥28% #### 五、GC对SSD的影响 - **正面**:维持长期可用空间,防止写入失败 - **负面**: - 写放大(WA):额外数据迁移增加NAND磨损 - 性能波动:GC占用带宽导致延迟尖峰 > 通过**TRIM命令**(通知SSD哪些数据可回收)可减少无效数据积累,优化GC效率[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值