JVM之垃圾收集器

阅读: 评论:0

JVM之垃圾收集器

JVM之垃圾收集器

垃圾收集器

    • Serial收集器
    • ParNew收集器
    • Parallel Scavenge收集器
    • Serial Old收集器
    • Parallel Old收集器
    • ==CMS收集器==
    • ==GI收集器==
    • GC日志

垃圾收集器就是内存回收的具体实现

Serial收集器

收集基本、发展历史最悠久的收集器,是一个单线程收集器(并不仅仅说明他只会使用一个CPU或者一个收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其它所有的工作线程,直到他工作结束)

优点:①简单而高效(与其他收集器的单线程比)
②获得最高的单线程搜集效率
Serial收集器对于运行在Client模式下的虚拟机来说是一个很好的选择。

ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本,是许多运行在Server模式下的虚拟机中首选的新生代收集器,可控参数、收集算法、对象分配规则,Stop The World、回收策略同Serial (目前只能和CMS收集器配合工作)
单CPU:由于存在线程交互开销,该收集器在通过超线程技术实现的两个CPU环境中都不能百分之百的保证可以超越Serial收集器
多CPU:随着CPU的数目增多,对于GC时系统资源的有效利用还是比较好的。

并行:多条垃圾收集线程并行工作,此时用户线程仍然处于等待状态,强调同一时间间隔,同一实体上的多个事件
并发:用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。强调同一时刻,不同实体上的多个事件。例:小学的妈妈煮饭的同时在洗菜,宏观上时同时的,但是是实施的时候还是有先后执行次序的,只不过宏观上认为是同时的。

Parallel Scavenge收集器

新生代收集器,采用复制算法,并行的多线程的收集器,ParNew,CMS收集器关注的是减短垃圾收集时用户线程的停顿时间,Parallel Scavenge收集器关注的是达到一个可控制的吞吐量(运行用户代码时间与CPU总消耗时间的比值,吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)),所以也经常被成为”吞吐量优先”收集器
参数:①控制最大垃圾收集停顿时间-XX:MaxGCPauseMillis
②实际吞吐量大小的:-XX:GCTimeRatio(垃圾收集时间占总时间的比率,是吞吐量的倒数)
GC的停顿时间是以牺牲吞吐量和新生代空间来换取的。
③:开关参数:-XX:+UseAdaptiveSizePolicy:此参数打开之后就不需要手动指定新生代的大小,以及各个区域比例和老年代的对象年龄等细节参数了,虚拟机会根据当前系统地运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种调节方式就被称为GC自适应的调节策略。也是与ParNew收集器的一个重要区别。

Serial Old收集器

Serial的老年代版本,单线程收集器,使用“标记-整理"算法。
用途:①JDK1.5及其以前与Parallel Scavenge收集器搭配使用
②作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。

Parallel Old收集器

Parallel Old是Parallel Scanvenge收集器的老年代的版本,使用多线程和”标记-整理“算法。
吞吐量优先收集器组合:Parallel Scavenge+Parallel Old
工作过程:

CMS收集器

以获取最短回收停顿时间为目标的收集器,也被成为”并发低停顿收集器”,使用”标记-清除“算法
选择CMS收集器来收集老年代的时候,新生代只能选择ParNew或者Serial收集器的一种。
实现步骤:
①初始标记(Stop The World):仅仅标记GC Roots根能直接联系的对象
②并发标记:在程序运行时进行并发标记,虽然耗时比较久,但是可以与用户线程一起工作。
③重新标记:(Stop The World)修改并发标记阶段,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。
④并发清除:在用户程序运行时,与用户线程一起工作,将标记的的对象进行清除。
工作过程:

缺点:①CMS收集器对于CPU十分的敏感。虽然会导致用户线程停顿,但是由于占用了一部分线程(CPU资源)而导致应用程序变慢,总吞吐量会降低。解决这一问题提出了“增量式并发CMS收集器”,使用操作系统中的抢占式来模拟多任务机制的思想,虽然会减少对用户的影响,但是效果依旧很一般,目前版本中,已经不再提倡用户使用。
②CMS收集器无法处理浮动垃圾。可能会出现“Concurrent Mode Failure"失败而导致另一次的Full GC产生,CMS并发清除阶段,用户程序还在运行着就会有新的垃圾不断产生,这一段部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时清理掉。
形象场景:垃圾车(收集器)在收垃圾,居民在丢垃圾,垃圾车将有垃圾的垃圾桶标记好了,按着标记去收垃圾,在垃圾车收垃圾的过程中,小区居民又向空的垃圾桶里丢了垃圾,由于空的垃圾桶在标记的时候没有被标记,垃圾车此次便不会收走这些垃圾,很好,居民这次扔的垃圾就成了浮动垃圾,这些垃圾就只能等到下一次垃圾车再收垃圾的时候带走了。
③由于CMS是一款基于“标记-清除”算法实现的收集器,所以会有大量空间碎片的产生,会给大对象的分配带来麻烦,所以CMS收集器在顶不住的时候,在FullGC时需要开启内存碎片的合并整理过程。

GI收集器

GI是一款面向服务端应用的垃圾收集器,HotSpot团队希望可以替换掉JDK1.5版本中的CMS收集器,与GC收集器相比,GI具备的特点:
①并行与并发
充分利用多CPU,多核环境下的硬件优势使用多个CPU来缩短Stop-The-World的时间,GI收集器依旧可以像CMS收集器一样通过并发的方式让Java程序继续执行,不需要停顿Java线程执行GC动作。
②分代收集
③空间整合
GI收集器在整体上看来使用的是“标记-整理”算法,但是在局部上看来又是基于“复制”算法实现的,由于使用了这两种算法,也就意味之在GI收集器运行期间不会产生内存空间碎片,收集后能提供规整的可用内存,有利于程序长时间运行。
④可预测的停顿
GI相对于CMS,GI收集器除了降低了停顿之外,还建立了可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗垃圾收集器上的时间不得超过N毫秒,这几乎已经是实时Java垃圾收集器的特征了。
在GI收集器之前,GC的范围一般都是整个新生代或者老年代,GI不再是这样,在使用GI收集器时,Java堆的内存布局就与其他收集器有很大区别,他将Java堆划分为多个大小相等的独立区域,虽然依旧保留着老年代和新生代的概念,但是新生代老年代已经不再是物理上的隔离了,而是一部分Region(不需要连续)的集合。
GI收集器之所以可以建立可预测的停顿时间模型,是因为它可以避免在Java堆中进行全区域的垃圾扫描,GI跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需要的时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region,这种使用方法保证了GI收集器在有效时间内可以获取尽可能高的收集效率。
为了避免在进行GC时,这个堆里的对象在另一个堆中有引用关系而导致的对Java堆的全堆扫描,虚拟机都是使用Remembered Set来避免安全堆扫描,GI收集器为了避免这一个问题,在每一个Region里都放了一个Remembered Set,虚拟机发现程序在对Reference类型的数据进行写操作时,会产生一个Write Barrier暂时中断写操作,检查Reference引用的对象是否处于不同的Region之中(在分代的例子中就是检查是否老年代中的对象引用了新生代中的对象 ),如果是,便通过CardTable把相关引用信息记录到被引用对象所属的Region的Remembered Set中。当进行内存回收时,在GC 根节点的枚举范围中加入Remembered Set即可保证不对全堆扫描也不会有遗漏。
步骤:
①初始标记:需要停顿线程,只是标记GC Roots能直接关联的对象,并修改TAMS的值,让下一个阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这阶段需要停顿线程,但耗时很短。
②并发标记:从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时很长,但可与用户程序并发执行。
③最终标记:修正在并发标记期间因用户程序继续运作而产生变动的那一部分标记记录,虚拟机将这段时间变化记录在线程Remembered Set中,这段时间需要停顿线程,但是可并行执行。
④筛选回收:首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划,这个阶段其实也是与用户程序一起并发执行。

GC日志

33.125:[GC[DefNew: 3324->152k(3712k),0.0025925 secs] 3324k->152k(11904k),0.0031680nsecs]

33.125 :时间参数,Java虚拟机启动以来经过的秒数
GC/Full GC:垃圾收集的停顿类型,并不能用来区分新生代和老年代
DefNew/Tenured/Perm:表示GC发生的区域,显示的区域名称与使用的GC收集器是密切相关的,不同收集器的名称可能不同。
3324k->152k(3712k):GC前该内存区域已使用容量->GC后该内存区域已使用容量(该内存区域总容量)
0.0025925 secs:内存区域GC所占用的时间,单位是秒。

本文发布于:2024-01-28 05:33:34,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063912185156.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:垃圾   收集器   JVM
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23