java 垃圾回收手动回收_Java垃圾回收(3)

java 垃圾回收手动回收

接下来是我的前两篇垃圾收集博客文章:

  1. GC热点概述
  2. 并行垃圾收集器

并发标记扫描

Hotspot中的并行垃圾收集器旨在最大程度地减少应用程序进行垃圾收集所花费的时间,这称为吞吐量 。 对于所有应用程序而言,这并不是一个适当的权衡取舍–有些应用程序还要求各个暂停时间较短,这被称为延迟要求。

并行标记扫描 (CMS)收集器设计为比并行收集器低的延迟收集器。 该设计的关键部分是尝试在应用程序运行的同时进行部分垃圾回收。 这意味着当收集器需要暂停应用程序的执行时,它不需要暂停那么长时间。

在这一点上,您可能会想: “并行和并发意味着不很相似吗?” 在GC上下文中, 并行意味着“使用多个线程同时执行G​​C”,而并行意味着“ GC与应用程序在其收集的同时运行”。

青年收藏

CMS中的年轻一代收集器称为ParNew ,它实际上使用了与我之前介绍的并行收集器中的Parallel Scavenge收集器相同的基本算法。

尽管在热点代码库方面,这与Parallel Scavenge还是一个不同的收集器,因为它需要与其他CMS交织其执行,并且还为Parallel Scavenge实现了一个不同的内部API。 Parallel Scavenge会假设与哪个永久性收集器一起使用-特别是ParOld和SerialOld。 赤裸裸地记住,这也意味着年轻的世代收藏家将停止世界。

终身收藏

与ParOld收集器一样,CMS终身收集器使用标记和清除算法,其中标记活动对象,然后删除无效对象。 当涉及到内存管理时,删除确实是一个奇怪的名词。 收集器实际上并不是在消隐内存的意义上删除对象,它只是将与该对象关联的内存返回到内存系统可以从中分配的空间–空闲列表。 尽管它被称为并发标记和清除收集器,但并非所有阶段都与应用程序的执行同时运行,其中两个阶段停止运行,四个阶段同时运行。

GC是如何触发的?

在ParOld中,当永久性堆中的空间不足时,将触发垃圾回收。 这种方法行之有效,因为ParOld只是暂停了应用程序的收集。 为了使应用程序在保管期收集期间继续运行,CMS收集器需要在保管期剩下足够的工作空间时开始收集。

因此,CMS将根据使用期限的长短来启动–想法是,剩余的可用空间是运行GC的机会之窗。 这称为启动占用率 ,用堆的满来描述,因此0.7的百分比为您提供了30%的堆窗口,以在堆用完之前运行CMS GC。

相数

触发GC后,CMS算法将包含一系列按顺序运行的阶段。

  1. 初始标记 –暂停所有应用程序线程,并将可从根对象直接访问的所有对象标记为活动。 这个阶段停止了世界
  2. 并发标记 –重新启动应用程序线程。 通过遵循在初始标记中标记的对象的引用,可以将所有活动对象都可传递地标记为可到达。
  3. 并发预清理 –此阶段查看在并发标记期间已更新或升级的对象或在并发标记期间已分配的新对象。 它更新标记位以指示这些对象是活动的还是死亡的。 此阶段可以重复运行,直到在Eden中有指定的占用率为止。
  4. 备注由于某些对象可能已在预清理阶段中进行了更新,因此仍然有必要停止世界以便处理残留的对象。 此阶段从根开始进行回溯。 它还处理参考对象,例如软参考和弱参考。 这个阶段停止了世界
  5. 并发扫描 –通过普通对象指针(OOP)表进行查找,该引用了堆中的所有对象,并找到了无效的对象。 然后,它将分配给这些对象的内存重新添加到其空闲列表中。 这是可以从中分配对象的空间的列表。
  6. 并发重置 –重置所有内部数据结构,以便将来能够再次运行CMS。

从理论上讲,在预清理阶段标记的对象将在下一个阶段-注释-进行查看,但是注释阶段使世界停滞不前,因此存在预清理阶段以尝试通过同时执行部分注释工作来减少注释暂停。 CMS最初添加到HotSpot时,此阶段根本不存在。 它是在Java 1.5中添加的,目的是解决年轻一代的垃圾回收导致暂停并立即添加备注的情况。 这句话还会引起停顿,这会造成更痛苦的停顿。 这就是为什么评论由伊甸园中的占用阈值触发的原因-目标是在年轻的发电机停顿之间安排评论阶段的中间时间。

备注阶段也处于暂停状态,而预清洁没有暂停,这意味着进行预清洁会减少在GC中暂停所花费的时间。

并发模式故障

有时CMS无法满足应用程序的需求,因此需要运行世界各地的Full GC。 这称为并发模式故障,通常会导致长时间的暂停。 当保有期限的空间不足以提升对象时,就会发生并发模式失败。 造成这种情况的原因有两个:

  • 提升的对象太大而无法放入内存中的任何连续空间。
  • 保有权使用的空间不足以说明要升级的活动对象的比率。

之所以可能发生这种情况,是因为在给定对象提升速率的情况下,并发集合无法足够快地释放空间,或者由于CMS收集器的继续使用导致了碎片化的堆,并且没有足够大的单个空间来将对象提升为对象。 为了正确“整理”使用年限的堆空间,需要完整的GC。

彼尔姆根

CMS默认情况下不收集permgen空间,并且需要启用?XX:+CMSClassUnloadingEnabled标志才能这样做。 如果在使用CMS时,如果未启用此标志就用完了permgen空间,它将触发Full GC。 而且,permgen空间可以通过类加载器之类的东西将引用保存到普通堆中,这意味着在收集Permgen之前,您可能会泄漏常规堆中的内存。 在Java 7中,来自类文件的String常量也分配给常规堆,而不是permgen,这减少了permgen的消耗,但也增加了来自permgen的常规堆中的对象引用集。

浮动垃圾

在CMS收集结束时,可能会删除某些对象(称为浮动垃圾)。 从初始标记开始取消引用对象时,就会发生这种情况。 并发的预清理和备注阶段可通过查看已创建,变异或升级的对象来确保对所有活动对象进行标记。 如果某个对象在初始标记和标记阶段之间已被取消引用,则它将需要整个对象图的完整回溯才能找到所有死对象。 这显然是非常昂贵的,并且备注阶段必须暂停,因为它是暂停阶段。

对于CMS用户而言,这不一定是一个问题,因为下一次运行CMS收集器将清除此垃圾。

摘要

并发标记和清除通过在应用程序运行的同时执行某些GC工作,减少了在并行收集器中观察到的暂停时间。 它不能完全消除暂停,因为其算法的一部分需要暂停应用程序才能执行。

我花了比我原本希望写这篇博客文章更长的时间-但是,如果您想知道我的下一篇文章何时发布,只需在此博客的右上角输入您的电子邮件即可通过电子邮件订阅。

参考: Insightful Logic博客上来自我们JCG合作伙伴 Richard Warburton的Java垃圾收集(3)

翻译自: https://www.javacodegeeks.com/2013/06/garbage-collection-in-java-3.html

java 垃圾回收手动回收

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值