Java垃圾回收(3)
这是我之前的两个垃圾收集博客文章中的内容:
- 热点GC概述 。
- 并行垃圾收集器 。
并发标记扫描
Hotspot中的并行垃圾收集器旨在最大程度地减少应用程序进行垃圾收集所花费的时间,这称为吞吐量 。 对于所有应用程序来说,这并不是一个适当的权衡取舍–有些应用程序还要求个别的暂停时间要短一些,这被称为延迟要求。
并行标记扫描 (CMS)收集器被设计为比并行收集器低的延迟收集器。 该设计的关键部分是尝试在应用程序运行的同时进行部分垃圾回收。 这意味着当收集器需要暂停应用程序的执行时,它不需要暂停那么长时间。
在这一点上,您可能会想: “并行和并发意味着不是很相似吗?” 在GC的上下文中, 并行意味着“使用多个线程同时执行GC”,而并行意味着“ 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算法将包含一系列按顺序运行的阶段。
- 初始标记 –暂停所有应用程序线程,并将可从根对象直接访问的所有对象标记为活动。 这个阶段使世界停滞不前 。
- 并发标记 –重新启动应用程序线程。 通过遵循在初始标记中标记的对象的引用,所有可移动对象都被可传递地标记为可到达。
- 并发预清理 –此阶段查看在并发标记期间已更新或升级的对象或在并发标记期间已分配的新对象。 它更新标记位以指示这些对象是活动的还是死亡的。 此阶段可以重复运行,直到在Eden中有指定的占用率为止。
- 备注由于某些对象可能已在预清理阶段中进行了更新,因此仍然有必要停止世界以便处理残留的对象。 此阶段从根开始进行回溯。 它还处理参考对象,例如软参考和弱参考。 这个阶段使世界停滞不前 。
- 并发扫描 –通过普通对象指针(OOP)表进行查找,该表引用了堆中的所有对象,并找到了无效的对象。 然后,它将分配给这些对象的内存重新添加到其空闲列表中。 这是可以从中分配对象的空间的列表。
- 并发重置 –重置所有内部数据结构,以便将来能够再次运行CMS。
从理论上讲,在预清理阶段标记的对象将在下一个阶段-注释-进行查看,但是注释阶段是使世界停滞不前,因此存在预清理阶段,通过同时执行部分注释工作来尝试减少注释暂停。 CMS最初添加到HotSpot时,此阶段根本不存在。 它是在Java 1.5中添加的,目的是解决年轻一代的垃圾回收导致暂停并在其后立即加上备注的情况。 这句话还会引起停顿,这会造成更痛苦的停顿。 这就是为什么评论由伊甸园的占用阈值触发的原因-目标是在年轻的发电机停顿之间安排评论阶段的中间时间。
备注阶段也处于暂停状态,而预清洁没有暂停,这意味着进行预清洁会减少在GC中暂停所花费的时间。
并发模式故障
有时CMS无法满足应用程序的需求,因此需要运行世界各地的Full GC。 这称为并发模式故障,通常会导致长时间的暂停。 当保有期中没有足够的空间来提升对象时,就会发生并发模式失败。 造成这种情况的原因有两个:
- 提升的对象太大而无法放入内存中的任何连续空间。
- 保有权使用的空间不足以说明要升级的活动对象的比率。
之所以会发生这种情况,是因为在给定对象提升速率的情况下,并发集合无法足够快地释放空间,或者由于CMS收集器的继续使用导致了碎片化的堆,并且没有足够大的单个空间来将对象提升为对象。 为了正确“整理”使用年限的堆空间,需要完整的GC。
彼尔姆根
CMS默认情况下不收集permgen空间,并且需要启用?XX:+CMSClassUnloadingEnabled
标志才能这样做。 如果在使用CMS时,如果未打开此标志就用完了permgen空间,它将触发Full GC。 而且,permgen空间可以通过类加载器之类的东西将引用保存到普通堆中,这意味着在收集Permgen之前,您可能会泄漏常规堆中的内存。 在Java 7中,来自类文件的字符串常量也分配在常规堆中,而不是分配在permgen上,这减少了permgen的消耗,但同时也增加了来自permgen进入常规堆的对象引用集。
浮动垃圾
在CMS收集结束时,可能会删除某些对象(称为浮动垃圾)。 从初始标记开始取消引用对象时,就会发生这种情况。 并发的预清理和备注阶段可通过查看已创建,变异或升级的对象来确保对所有活动对象进行标记。 如果某个对象在初始标记和标记阶段之间已被取消引用,则它将需要整个对象图的完整回溯才能找到所有死对象。 这显然是非常昂贵的,并且备注阶段必须暂停,因为它是暂停阶段。
对于CMS用户而言,这不一定是一个问题,因为下一次运行CMS收集器将清除此垃圾。
摘要
并发标记和扫描通过在应用程序运行的同时执行某些GC工作,减少了在并行收集器中观察到的暂停时间。 它不能完全消除暂停,因为其算法的一部分需要暂停应用程序才能执行。
我花了比我原本希望写这篇博客文章更长的时间-但是,如果您想知道我的下一篇文章何时发布,只需在此博客的右上角输入您的电子邮件即可通过电子邮件订阅。
翻译自: https://www.javacodegeeks.com/2013/06/garbage-collection-in-java-3.html
Java垃圾回收(3)相关推荐
- 假期三天,我肝了万字的Java垃圾回收,看完你还敢说不会?
大家好,我是狂聊,上一篇已经把 Jvm 的运行区数据和类加载机制聊完了. 今天来说说 Java 垃圾回收,高频面试问题. 提纲附上,话不多说,直接干货 1.什么是垃圾回收? 垃圾回收(Garbage ...
- java垃圾回收机制_笔记 | Java垃圾回收机制
本文经授权转载自程序员杂货铺(ID:speakFramework) 垃圾回收 最近上海的小伙伴是不是要被强垃圾分类搞疯了???哈哈哈哈 上海是个走在前列的城市啊,不光骑自行车闯红灯要被罚钱,垃圾不分类 ...
- 细述 Java垃圾回收机制→Types of Java Garbage Collectors
本文将会介绍各种不同类型的Java垃圾回收器.垃圾回收是Java用来将程序员从分配和释放内存的琐事中解放出来的自动过程. Java有四种类型的垃圾回收器, Serial Garbage Collect ...
- 细述 Java垃圾回收机制→Java Garbage Collection Monitoring and Analysis
本文非原创,翻译自Java Garbage Collection Monitoring and Analysis 在Java中为对象分配和释放内存空间都是由垃圾回收线程自动执行完成的.和C语言不一样的 ...
- Java垃圾回收工作原理
在C++中,在heap上分配对象比在stack上分配对象更加昂贵.程序需要找到合适的内存块,再返回内存的地址.但是在Java中垃圾回收器显著地提高了在heap上分配对象的速度.听起来会有些怪,但是这就 ...
- Java 垃圾回收机 GC Roots详解(Garbage Collection Roots)
背景: 之前面试阿里支付宝,被问到常见的GC Root 是什么? 当时自己支支吾吾,明明自己看过深入理解Java 虚拟机这本书,但是就是回答不上来. 后来自己工作中,遇到内存泄漏问题.我百度,下载了M ...
- Java垃圾回收机制(Garbage Collection)
引用博客地址:http://www.cnblogs.com/ywl925/p/3925637.html 以下两篇博客综合描述Java垃圾回收机制 第一篇:说的比较多,但是不详细 http://www. ...
- java垃圾回收机制串行_Java垃圾回收机制
Java语言是一门自动内存管理的语言,不再需要的对象可以通过垃圾回收自动进行内存释放. Java运行时内存区域划分 JVM将Java程序运行时内存区域划分成以下几个部分: 程序计数器(Program ...
- java垃圾回收机制_JVM的垃圾回收机制——垃圾回收算法
一.Java垃圾回收机制 在java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行.在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者 ...
- java垃圾回收根对象_Java垃圾回收怎么理解?
展开全部 Java的堆是一个运行时数据区,类的实例(对象)从中62616964757a686964616fe58685e5aeb931333339653664分配空间.Java虚拟机(JVM)的堆中储 ...
最新文章
- 微软职位内部推荐-Senior Software Engineer-Eco
- VCL 中的 Windows API 函数(6): BeginDeferWindowPos
- 用execSQL语句建表时提示“syntax error”原因及解决方法
- Tips:重装系统后Anaconda目录在开始菜单消失问题
- 左神算法:二叉树的按层打印与ZigZag打印(Java版)
- uds帧格式_UDS诊断帧
- 二维数组各行求和_JS数组reduce()方法详解及高级技巧
- 代码管理学:一时不检查,工作必走样
- Arbor Networks Spectrum新安全平台发布:高级威胁平台通过内部企业网络连接互联网上的攻击...
- 【教程】Edraw Max使用教程:Edraw Max快速入门指南
- 毕业论文页码与目录自动生成
- word-单独设置某一页的页眉或页脚
- Linux mail 命令(smtp.163.com)
- qq大学认证如何修改随意修改认证内容
- 基于java springboot扫码点餐小程序源码(毕设)
- 励志必看-------没有伞的孩子必须努力奔跑!
- 数据产品经理修炼手册_产品经理技能点修炼之路(附薪资)
- 借助Aspose.Cells组件,实现PowerBuilder Datawindow 数据导出到Excel
- 如何用纯 CSS 创作一个小和尚
- Yaml编程语言学习
热门文章
- 计算机视觉论文doc,嘉炬-计算机视觉论文资料.doc
- 【1】flink-source读取数据
- 求三个数的最大最小值
- ubuntu系统下安装docker并部署Springboot+mysql+redis
- 纯注解开发配置spring
- oidc auth2.0_将Auth0 OIDC(OAUTH 2)与授权(组和角色)集成
- spring的bean范围_Spring Bean范围
- java分页中显示更多_早期更多失败– Java 8
- gatling的环境配置_将Gatling集成到Gradle构建中–了解SourceSet和配置
- java源文件编译成jar_从源文件和JAR文件构建Java代码模型