首页 > 编程知识 正文

java垃圾回收算法有哪些,javajvm垃圾回收原理

时间:2023-05-05 03:09:13 阅读:16420 作者:1996

在上述文章《【JVM系列二】深入理解JVM 垃圾回收算法》中,JVM对象存活的判定算法(引用计数法、可达性分析法--GC Roots引用链)和常用的垃圾回收算法)标记-擦除、复制、标记-整理本文要在分析高清的HotSpot VM上实施这些算法,必须严格考虑算法执行效率,以保证虚拟机的有效运行。

目前主流商用虚拟机采用“分代收集”垃圾算法,主要根据对象的生存周期将堆内存分成几个块。 一般将Java堆分为cxdsy代和老年代,根据其年龄代对象的特点采用不同的回收算法。 在cxdsy层代中,每次GC时大部分对象都死了,而且只有很少的生命存在,因此选择复制算法可以以很少的生命对象复制成本回收。 另一方面,在旧世代,由于对象的生存率高,也没有分配保证其的额外空间,所以使用“标签清除”或“标签整理”算法进行GC。

GC类型:

针对minorgc:cxdsy世代的GCMajor GC :针对前一代的GCFull GC :针对永久世代、cxdsy世代、前三者的GC(JDK1.7 )一、垃圾回收器,上述介绍的回收算法为内存回收算法

因为JVM规范没有规定如何实现垃圾收集器,所以每个供应商和版本都将不同的虚拟机实现为垃圾收集器,以便用户可以将每个Java堆空间中使用的收集器与APP应用程序的特性和要求相匹配

以下是JDK 1.7版HotSpot VM虚拟机的垃圾收集器: 这七个作用于不同世代的收集器。 其中,如果两个收集器具有连接(蓝色),则表示它们可以组合使用。

注意:没有最佳组合。 必须为特定的APP应用程序场景选择最佳收集器。

方法论

cxdsy层代可用的GC收集器:串行复制、ParNew、并行扫描等。

分配对象时,在Eden空间不足时触发Minor GC。 均使用具体实现算法,原理上一致。 将eden和from的生存对象复制到to; 部分对象因某种原因晋升为old (如to区空间不足,对象生存次数超过15次); 清除eden、from、from和to交换身份直到发生下一次GC。cxdsy代:

老年代可用的GC采集器: CMS、串行old、并行old等,分析如下。

永久世代和老世代诱发GC时,除CMS外均诱发全GC。

首先按照cxdsy世代配置的GC方式进行MinorGC; 进而按照老年代配置的GC方式对老年代和永久一代进行GC; JVM预计在minor GC后可能会发生晋升失败时,将Young、Old、Perm按照老一辈配置的GC方式直接进行GC。复制

老年代:

单核CPU可能会延迟并行处理。

术语介绍:

STW :暂停整个APP应用程序线程,并且仅GC线程正在运行,这可能需要很长时间; 并发:更复杂,GC可能会断开APP应用程序的CPU连接。1、串行(Serial)VS 并行(Parallel)

并行—多个垃圾回收线程并行运行。 此时,用户线程处于待机状态; 并发:用户线程和垃圾回收线程同时运行,不一定并行,存在交叉执行的可能性。 用户程序继续运行,垃圾回收线程在另一个CPU上运行。 注:此处介绍的“用户线程”=“APP应用程序线程”。

1.1串行收集器这是cxdsy代单线程串行收集器。 (2、STW(Stop The World)VS 并发(Concurrent))

这意味着必须只使用一个CPU或一个收集线程来完成收集工作,并在垃圾回收正在运行时暂停所有其他工作线程,直到收集完成。

3、并行(Parallel) VS 并发(Concurrent)

串行、停止

-the-world(暂停应用线程)

适用场景:

单CPU、cxdsy代小、对暂停时间要求不高的应用;是client级别或32位windows上的默认选择。

对象直接分配在老年代的情况:

对象大小超过eden space大小大对象(PretenureSizeThreshold)

晋升规则:

经历多次Minor GC仍存活的对象;To Survivor放不下的(满或剩余空间不够)对象直接晋升到老年代。1.2 ParNew 收集器

ParNew收集器其实就是Serial串行收集器的多线程版本。(并行复制

除了使用多线程进行GC外,其它均与Serial 收集器完全一样,如:控制参数(-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、Stop The World、对象分配规则、回收策略等。

注:虽然ParNew没有多大创新之处,但是它却是许多运行在Server模式下的JVM首选的cxdsy代收集器,主要是除了Serial收集器外,目前只有它可以与老年代的CMS搭配使用。

ParNew 收集器是在老年代使用-XX:+UseConctldmlaSweepGC参数选项后的默认cxdsy代收集器,当然也可以使用-XX:UseParNewGC参数选项来强制选用它。

特性:

Parallel(并行)、Stop-the-world;可以认为是Serial Copying的多线程版本,各项特征与之基本一致;可以搭配CMS、Serial Old;不可搭配Parallel Old。

1.3 Parallel Scavenge 收集器

这也是一个cxdsy代收集器,同样是采用复制算法实现,同时也是并行多线程收集器。

咋描述与ParNew一样?

Parallel Scavenge关注点与其他收集器不同,ParNew、CMS等收集器的关注点是尽可能缩短垃圾收集器时用户线程的停顿时间(缩短STW),而Parallel Scavenge收集器的目的是达到一个可控制的吞吐量(Throughput)。

吞吐量:CPU用于运行用户代码的时间与CPU总消耗时间的比值,即:

Throughput = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)

STW停顿时间越短越适合需要与用户交互的应用,较快的响应速度能提升用户体验;而提高吞吐量则可以提高CPU的效率,尽快地完成应用的运算任务,主要适合在后台运算而不需要与用户有太多交互的任务。
作为一个吞吐量优先的收集器,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整停顿时间,这就是 GC 的自适应调节策略(GC Ergonomics)。

特性:

Parallel(并行)、Stop-the-world并行线程数默认值:(亦可强制指定线程数(-XX:ParallelGCThreads=4))CPU核数<=8:=CPU核数CPU核数>8:=(3+CPU核数*5)/8会根据Minor GC的频率、时间等动态调整Eden/S0/S1的大小,可取消这一特性(-XX-UseAdaptivesizePolicy)

适用场景:

多CPU、对吞吐量要求高而无需太多交互的应用;是Server级别(2核CPU2G内存)机器上的默认选择。

对象直接分配在Old的情况:

在TLAB和eden上分配失败,且对象大于eden的一半大小;PretenureSize Threshold参数是无效的。

晋升规则:

经历多次Minor gc仍存活的对象:规则和参数都比Serial Copying复杂;To Survivor放不下的(满或剩余空间不足)对象直接晋升到老年代。1.4 Serial Old 收集器

Serial Old (Serial MSC)是Serial收集器的老年代版本,单线程,采用 “标记-整理”算法。

该收集器的主要意义是应用在Client模式下的JVM使用。

如下图,与上面介绍的年轻代的Serial收集器搭配使用:

特性:

Serial(串行)、Stop-the-world;使用算法:tldmla-Sweep-Compact(标记-整理);由于是单线程,GC造成的暂停时间可能会很长,可使用-XX:+PrintGCApplicationStoppedTime查看暂停时间。

适用场景:

是client级别或32位windows上的默认选择1.5 Parallel Old 收集器

Parallel Old(Parallel Cpmpacting) 是 Parallel Scavenge 收集器(吞吐量优先)的老年代版本。多线程,采用“标记-整理/压缩”算法。

该收集器在JDK1.6 后才提供,在此之前,如果cxdsy代选择Parallel Scavenge收集器,则老年代只能选择Serial Old。

如下图,是“吞吐量优先”的GC组合,在注重吞吐量以及CPU资源敏感的场景,可以优先考虑 Parallel Scavenge+Parallel Old 组合,年轻代与年老代的GC都是多线程并行版本。

特性:

Parallel(并行)、Stop-the-world;使用算法:tldmla-Compact算法较为复杂。

Parallel Compacting 算法的详细描述:

适用场景:

多核CPU、对暂停时间较敏感的应用,吞吐量优先;是Server级别(2核CPU 2G内存)机器上的默认选择。1.6 CMS收集器

CMS (Concurrent tldmla Sweep,并发标记清除) 收集器是一种以获取最短回收停顿时间为目标的收集器(最短STW)。

基于“标记-清除”算法实现,也叫并发停顿收集器(Concurrent Low Pause Collector)。

执行过程:

初始标记(CMS initial mark):标记 GC Roots 引用链能直接关联到的对象,速度很快;并发标记(CMS concurrent mark):进行 GC Roots Tracing的过程;重新标记(CMS remark):修正并发标记期间的变动部分,停顿时间比初始标记稍长,但远比并发标记短;并发清除(CMS concurrent sweep)

其中,并发标记与并发清除是耗时最长的,但是可以与用户线程同时工作(并发),所以,从总体上来看,CMS的内存回收过程是与用户线程一起并发执行的。

特性:

Parallel、Concurrent使用算法:tldmla-Sweep算法更为复杂缩短GC暂停时间,但相当复杂,增加了GC总时间默认并发线程数=(cxdsy代并行GC线程数+3)/4,也可用-XX:ParallelCMS Threads=2来指定对Perm Generation也可启用CMS:-XX:+CMSPermGenSweepingEnabled,-XX:+CMSClassUnloadingEnabled

缺点:

GC总耗时长与应用抢占CPU:在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用部分线程(CPU资源)而导致应用程序变慢,总吞吐量降低。其实,面向并发设计的程序都对CPU资源敏感。无法收集浮动垃圾:可能在“Concurrent Mode Failure”失败时导致另一次Full GC。由于CMS在并发清理阶段,用户线程还在运行,伴随着程序的运行自然会产生新的垃圾,而这部分垃圾称为“浮动垃圾”,它们是出现在标记之后,CMS无法在本次收集中回收它们,只能等待下次GC再处理。标记-清除算法带来的内存碎片:空间碎片过多,就算老年代总体还有很大空闲内存,在给大对象分配内存时,可能无法找到足够大的连续空间,而不得不提前触发一次Full GC。

因此,CMS提供了一个参数:-XX:+UseCMSCompactAtFullCollection(默认开启),当CMS顶不住要Full GC 时开启内存碎片的合并整理过程,但内存碎片是无法并发的,停顿时间将变长;

另外还有一个参数:-XX:CMSFullGCsBeforeCompaction,用于执行多少次不压缩的Full GC后,跟着来一次压缩整理(默认值为0,表示每次进入Full GC时都进行碎片整理)。

适用场景:

STW暂停时间短,对追求最快响应速度的应用,尤其是互联网应用很适用。

面试可能会经常问CMS,CMS的优缺点、过程描述。

待续...

参考:《深入理解Java虚拟机》

●史上最强Tomcat8性能优化

●阿里巴巴为什么能抗住90秒100亿?--服务端高并发分布式架构演进之路

●B2B电商平台--ChinaPay银联电子支付功能

●学会Zookeeper分布式锁,让面试官对你刮目相看

●SpringCloud电商秒杀微服务-Redisson分布式锁方案

查看更多好文,进入公众号--撩我--往期精彩

一只 有深度 有灵魂 的公众号0.0

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。