当前位置: 首页 > 网络应用技术

十个单词长文字带您在-Java中对7种类型的JVM垃圾收集器的深入了解

时间:2023-03-05 18:28:33 网络应用技术

  尽管通用垃圾收集算法是固定的,但是如何由虚拟机使用的GC收集器专门确定内存恢复,并且在虚拟机中通常有一个以上的GC收集器。收集算法,让我们看一下7 GC如果垃圾收集算法是一种用于内存回收的方法,则垃圾收集器是内存恢复的特定实现。

  对于常见的垃圾收集算法,您可以阅读本文:Java中的常见JVM垃圾收集算法。

  热点虚拟机的常见垃圾收集器如下:

  上图显示了7个对不同世代作用的收藏家。如果两个收藏家之间存在连接,则意味着可以使用它们。虚拟机所定位的区域表示它属于新一代收藏家还是较旧的收藏家。LET查看7的简短图7垃圾收集器。

  查看默认设置命令:

  java -xx:+printCommandlineFlags- version

  检查默认垃圾收集器的详细信息命令,通过新一代的名称确定垃圾收集器

  java -xx:+printgcdetails- version

  哪些垃圾收集器更准确地使用

  java -xx:+printflagsfinal

  我的JDK1.8的信息如下

  Psyounggen代表了由平行的Scavenge收藏家管理的新一代,帕罗德(Paroldgen)说,由平行老年人管理的老人。

  Java -XX的结果:+PrintFlagSfinal证实了我们的想法:

  默认垃圾收集器:

  JDK1.7默认垃圾收集器平行清除+平行旧(老年)

  平行的和谐。名词都是并发编程中的概念。在垃圾收集者的评论中,他们可以解释如下。

  并行:指多个垃圾收集线程并行工作,但此时用户线程仍在等待。

  并发:指的是用户线程和垃圾收集线程(但不一定要交替执行),用户程序继续运行,并且垃圾收集程序在另一个CPU上运行。

  系列是最基本的垃圾收集器。使用了复制算法,在JDK 1.3.1之前,它曾经是年轻一代的唯一垃圾收集者。连续垃圾收集器是指序列号是一个单线收集器。它不仅使用CPU或线程来完成垃圾收集工作。虽然必须悬挂垃圾收集,但所有其他工作线程都必须暂停,直到所有其他工作线程被悬挂直到收集垃圾收集到结束为止。

  STW在背景中由虚拟机自动启动和完成。在用户的无形情况下,用户正常工作的线程将停止。对于许多应用程序,这是不可接受的。

  尽管串行垃圾收集器需要在收集垃圾收集期间暂停所有其他工作线程,但它既简单又有效。对于有限的单个CPU环境,没有线程交互开销,可以获得最高的单线垃圾收集效率。因此,收藏家仍然是在客户模式下运行的年轻一代垃圾收集器。

  对于具有较强相互作用的应用,此类垃圾收集器是不可接受的。该收集器通常在Javaweb应用中不使用。

  年轻一代使用复制算法,而老年则使用该系列的部分。

  串行和串行旧匹配示意图:

  -XX:+使用erialgc参数指定新一代和老年,两个串行垃圾收集器,即串行+串行旧。

  串行旧版本是串行收藏家的旧版本。它也是一个单线收集器,使用“标记组织”算法。该收集器的主要意义是在客户端模式下使用虚拟机。如果在服务器模式下,它具有两个主要用途:一个是:用于JDK 1.5和以前的版本,带有并行的清除收集器。另一个被用作CMS Collector的储备计划。当收集并发模式故障时使用。这些点将在以下内容中详细说明。

  -XX:+使用erialgc参数指定新一代和老年,两个串行垃圾收集器,即串行+串行旧。

  -XX:+UseParnewGC的新一代Parnew,默认情况下,老年人使用串行旧。

  -xx:+useparallelgc的新一代平行清除,默认情况下,老年人使用串行旧。

  Parnew Collector实际上是串行收集器的多线程版本,该版本是平行垃圾收集器。此外,还使用多个线程进行垃圾收集,其余的行为与串行收集器完全相同。在实施方面,这两个收藏家也共享相当大的代码。

  Parnew收集器是在服务器模式下运行的虚拟机中新一代收集器的选择。与性能无关的原因之一是,除了串行收藏家,只有Parnew可以与CMS收集器合作工作。它是独立实施的;其余的收藏家使用了一些框架代码)。

  由于单个CPU具有多线程相互作用的开销,因此在单个CPU的环境中,Parnew收集器可能没有比串行收集器更好的效果。以限制垃圾收集的螺纹数量。

  -xx:+useconcmarkSweepGC新一代使用Parnew,CMS用于老年。

  -XX:+UseParnewGC的新一代Parnew,默认情况下,老年人使用串行旧。

  平行的Scavenge Collector是新一代收藏家。它也是使用复制算法的收集器。这是一个并行多线收集器。

  它重点关注程序以达到可控吞吐量(虽然,运行用户代码时间/CPU总消费时间的CPU,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),也就是说)首选吞吐量。高吞吐量可以使用CPU时间来最大化效率并尽快完成程序的操作任务。它主要应用于与后台用户交互的任务,这意味着在完成任务后,良好的响应速度可以改善用户体验。这个场景需要较短的GC时间和较短的SWT。目前,最好使用CMS)。

  自适应调整策略也是平行的清除收藏家和Parnew收集器之间的重要区别。它也通常称为“吞吐量优先级”收集器。

  并行的清除收集器提供了两个参数来准确控制吞吐量:-XX:GCTIMERATIO参数,该参数控制最大垃圾集合-XX:MAXGCPAUSEMILIS参数和-xx:gctimeratio参数,直接通过吞吐量设置。

  -XX:MAXGCPAUSEMILIS参数允许毫秒数大于0的值。收集器将确保内存恢复的成本不会尽可能多地超过设定值。GC的暂停通过牺牲吞吐量和新一代的空间缩短:该系统具有较小的新一代,300MB新一代的收藏必须为500MB。每秒一次,每秒一次,每次停顿100毫秒,现在它变成5秒钟的收集,每次暂停70毫秒。确实减少了,但吞吐量也下降了。

  -XX:GCTIMERATIO参数的值应为整数大于0和小于100,即垃圾收集的总时间比,这与吞吐量的倒计时相当。如果此参数设置为19,允许的最大GC时间占总时间的5%(即(IE 1+19)),默认值为99,这是允许的最大1%(即1/(1+9999999))垃圾收集时间。

  还有一个并行清除收集器-xx的参数:+useadaptivesizepolicy。机会根据当前系统的操作收集性能监视信息,并动态调整这些参数以提供最合适的暂停或最大吞吐量。这种调整方法称为GCADAPTIVE调整策略(GC人体工程学)。

  -xx:+useparallelgc的新一代平行清除,默认情况下,老年人使用串行旧。

  -xx:+使用平行清除和平行旧的useParalloldGC的新一代。

  平行的Scavenge的老年版,通常用于追求CPU吞吐量。此收集器仅在JDK 1.6中提供。它们是在垃圾收集过程中由多个GC线程并联执行的,并且所有用户线程均被暂停以使用“标记级别” algorithm。追求吞吐量。

  -xx:+使用平行清除和平行旧的useParalloldGC的新一代。

  CMS(并发标记)收集器不同于平行的清除和平行的旧收藏家。它是一个针对最短恢复时间的收集器。在目前,Java应用程序的很大一部分集中在Internet网站或B/S系统的服务器上。这种类型的应用程序非常重视服务的响应速度。我希望该系统是为用户带来更好体验的最短时间。CMS收集器非常符合此类应用程序的需求。

  CMS收集器通常是基于“标记-Crear”算法实现的。它的特定操作过程比以前的收藏家更为复杂,包括:

  主要步骤是:初始标记(CMS初始标记),CMS并发标记,CMS注释,CMS并发扫描。

  由于使用标记算法,初始标记并重新标记这两个步骤仍然需要“停止世界”。初始标记只是标记GC根对象。速度很快。并发标记阶段是执行GC Rootstracicing的过程。标记记录,此阶段的暂停时间通常比初始标记阶段稍长,但比并发症标记时间短得多。

  由于长时间的并发标记和并发间隙过程可以与用户线程一起使用,因此,从一般来看,CMS收集器的内存回收过程是使用用户线程执行的。它被认为是并发垃圾收集器。

  2.6.1.1初始标记这是两次CMS中的停止障碍之一。此步骤的作用是标志的对象,有两个部分:

  为了加快此阶段的处理速度并减少暂停,可以打开初始标记并行-XX:+CMSParalinitialirmarkNabled。同时,标记为平行标记的线程的数量不应超过螺纹的数量,而不是CPU的数量。

  2.6.1.2使用应用程序执行并发标记阶段。这个阶段主要做两件事:

  并发标记阶段仅负责已更改为肮脏状态的卡标记,并且不负责处理;由于此阶段与用户线程并发,因此可能导致并发模式故障。

  2.6.1.3预切阶段用于处理由于参考关系的变化而导致上一阶段变化而未标记的幸存对象。引文点为6;然后节点3的卡将被标记为脏。

  最后,将6标记为生存,肮脏的区域消失了,如下图所示:

  2.6.1.4可以中断其目的以清除预定阶段的阶段是减少重新标记的工作量并减少悬架时间。可以取消此阶段,并且使用-xx:-cmsprecleanenabled参数,表明未执行前任前任。

  退出条件是:

  由于重新标记是CPU独有的,如果新一代GC发生,它将立即触发重新标记的一次,然后可能很长。5秒。它可以持续5秒钟的原因是期望您可以在这5秒内拥有一个年轻的GC,并预先将年轻一代供参考(预测是并发),进行重新标记的下一个阶段,扫描扫描对旧一代的参考时间;在很大程度上,避免新一代GC并重新标记重新标记,并尽可能最大程度地减少标记停顿。

  2.6.1.5最终重新标签和最终标签也称为重新标记。在此阶段,第二个单词将引起。这个阶段的任务是完成整个旧一代的所有生存对象。重新标记的记忆范围是整个堆,包括年轻的gen和old gen。

  为什么扫描新一代,因为对于老年的对象,如果引用了新一代的对象,则将其视为生存的对象。该对象被用作CMS的“ GC根”进行扫描旧一代。因此,对于老年人来说,老一代的新一代新一代也将被老一辈视为“ GC根”。

  在此阶段需要很长时间时,您可以添加参数-xx:+cmsscavengengefreremark。在重新标记之前,执行年轻的GC一次以恢复年轻皮带的无用对象,并将物体放入幸存的皮带中,或者晋升为晋升,以晋升为晋升幸存者或晋升为促进晋升,以晋升为晋升为晋升。在老年时,当年轻的皮带扫描时,您只需要扫描幸存者地区的对象即可。通常,幸存的皮带很小,这大大减少了扫描时间。

  由于以前的预处理阶段是与用户线程同时执行的,因此,此时,年轻皮带的目标可能已经发生了很大的变化。这个词,因此通常,当CMS在最后的备注阶段运行时,它足够干净,可以干净。此外,您还可以打开并行收集:-xx:+cmsparallelremarkemarkenabled。

  2.6.1.6定期清理主要是要删除没有标签和回收空间的人。

  由于用户线程在CMS并发清洁阶段仍在运行,因此在运行程序操作后自然会有新的垃圾。垃圾的这一部分出现在标签过程之后。当GC时再次清洁垃圾时,该部分称为“浮动垃圾”。

  2.6.1.6设备重置此阶段是最后阶段,重置CMS数据的结构以准备下一个GC。

  2.6.2.1由于用户线程和GC过程中的GC线程的平行而引起的低吞吐量,有线开关的附加开销不如CPU吞吐量不如停止在GC过程中停止所有用户线程的高度高。

  2.6.2.2减少备注阶段以停止。通常,CM的GC是备注阶段的80%。如果您发现备注阶段的暂停很长,可以尝试添加此参数:-XX:+CMSSSCAVENGERFREREMARK在执行备注操作之前一次进行年轻的GC。目的是减少对老年人的无效参考并减少。发言期间的开销。

  2.6.2.3内存碎片问题CMS基于标记清除算法。CMS仅删除无用的对象,并且不会压缩内存,这将导致内存片段。当空间太多时,它会给大型物体分配带来很大的麻烦。通常,仍然有很多空间容纳老年人,但是您找不到足够大的连续空间来分配当前物体。您必须先再次触发完整的GC。,即串行GC,效率非常低。

  为了解决此问题,CMS Collector提供了-XX:+USERCMSCOMPACTATFULLCOLLECTION SWECT参数(open默认值)。当CMS收集器无法保留完整的GC时,它用于打开合并和整理过程。该过程是不可替代的,空间碎片的问题已经消失,但是停顿必须增长。

  目前,我们需要使用此参数:-xx:cmsfullgcsbeforecompaction = n。这意味着在上次CMS并发执行后将执行多少次。默认值为0,这意味着每个完整的GC被压缩。如果将CMSFulllGCSBeForeCompaction配置为10,上面提到的第一个条件将变成真正的完整全GC每10次压缩。

  2.6.2.3并发模式故障此异常发生在CMS回收时发生。在执行CMS GC的过程中,业务线程也在运行。当轻带空间充满时,当执行年轻的GC时,需要将幸存的物体放入老年。目前,此时的空间还不够老年。

  设置CMS触发时机有两个参数:

  在JDK 1.6中,CMS收集器的起始阈值已增加到92%。

  -XX:+USECMSInitiatItiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatiatieniticcupaction,那么JVM仅首次使用设置值,然后后续调整将导致上述参数工作。

  为什么这两个参数?

  因为用户线程需要在垃圾收集阶段运行,所以还需要为用户线程保留足够的存储空间,因此CMS收集器无法等到老年几乎充满了老年,然后将其收集收集它以供收集。必须保留一部分空间以在收集时提供程序操作。

  CM的前五个阶段是标记为幸存的物体。除了“初始标记”和“重新标记”阶段之外,其他三个阶段还使用用户线程运行。对象,用户线程同时将新对象改进了新对象。清洁工作尚未开始。旧的gen没有空间容纳更多物体。在这个时间里,收藏家收回了整个垃圾,这导致了很长时间的停车。

  注意:参数应设置一个合理的值。设置很大,这将增加并发模式故障的频率。设置很小,CMS频率将增加。因此,应根据应用程序的操作选择合理的值。如果您发现已设置这两个参数,则将导致完整的GC。设置很小,可以引起频繁的CMS GC,表明您的空间太小,您应该增加老年的大小。

  运行CMS收集器时,可能会有两种类型的故障:

  2.6.3.1并发模式失败无法适应并发模式,而新一代的GC促销不适合旧一代(实际上,上面有上面的演讲):

  2.6.3.2令人鼓舞的失败有足够的空间适合老年,但是由于严重的分裂,它无法容纳新一代促销的对象,并且晋升失败了。

  促进失败的原因是碎片化是严重的,因此该问题的解决方案是如何减少碎片问题。CMS提供了两个参数来组织和压缩片段:-xx:+usecmscompactatulclection此功能是为了组织的。并在执行FullGC时压缩片段。-xx:cmsfulllgcsbeforecompaction = n此参数是为了在执行时会压缩时代内存。通过设置这两个参数,这些片段已有效地进行了优化。片段的时间是耗时的操作,因此有必要谨慎设置它。

  结合上述参数配置,CMS的某些参数如下:

  -xx:+useconcmarkSweepGC激活的CMS收集器,默认错误false

  -xx:concgcthreads = n设置CMS线程的数量

  -xx:+usecmsinitiatiatiatiatiatiatiatiatiationly仅确定是否CMS

  

  -xx:+cmsparallearRemarkenabled并行运行,以运行最终分数阶段以加快最终标记

  -xx:+usecmscompactalllcollection,每个触发CMS完整GC都会组织一次,默认为false

  -xx:cmsfulllgcsbeforecompaction = n在几个完整的GC(默认GC)(即,默认情况下)压缩压缩后,将片段缩小一次。

  -XX:+CMSClassunLoadingEnabled允许CMS收集永久频段。默认值将不会收集。收集后,将触发完整的GC。

  -XX:+CMSSSCAVENGENGENGERFREREMARK最终标签以在默认错误之前迫使小型GC。

  G1垃圾收集器是一种新的垃圾收集器,在JDK1.7中正式使用。Oracle正式计划将G1变成JDK9中的默认垃圾收集器,以替换CM。G1的特征如下:

  G1垃圾收集算法主要用于多CPU和大型内存服务。在满足较低的悬架时间时,吞吐量尽可能多,并且记忆片段同时处理。

  以前的垃圾收集器(例如CMS),在堆内存中使用的GC模型如下:

  年轻一代:伊甸园 + 2个幸存者

  老年:旧空间

  永久发电:1.8之前的珀斯空间

  元空间:1.8之后的Metaspace

  这些记忆空间的特征是它们必须是连续的地址。因为它在逻辑上是连续的;这些领域包含逻辑年轻人和老一辈。某个地区可能是伊甸园,可能是幸存者,也可能是老年人。这样,我们不再需要设置每一代人来建立每一代,而不必担心每一代记忆足够。

  可以通过-xx:g1heapionsionsize参数指定堆内存中区域的大小。大面积只能为1m,2m,4m,8m,16m和32m。在初始化过程中估计区域的实践大小。具体实现如下:

  默认情况下,根据2048副本将堆内存分开,最后获得合理的尺寸。

  这些领域的一部分包括新一代,新一代的垃圾收集仍然使用悬挂所有应用程序线将幸存物体复制到老年或幸存者空间的方法。染色年龄也分为许多领域。G1收集器通过将对象从一个区域复制到另一个区域完成了清理工作。这意味着在正常处理过程中,G1完成了堆的压缩(至少是堆的部分压缩),以便将没有CMS内存分裂问题。

  G1收集器的堆内存GC模型如下:

  每个区域都用E,S,O和H标记,表明每个区域在Runtime中充当一个角色。在G1中,还有一个称为巨型区域的特殊区域,表明区域存储了巨大的物体。

  如果物体占据的空间超过分区容量的50%,则G1收集器认为这是一个巨大的对象。

  这些巨型物体将直接在老年中分发,但是如果它是一个短期巨型对象,它将对垃圾收集器产生负面影响。

  为了解决这个问题,G1将用于存储巨大对象的巨大区域划分。如果没有使用巨型对象安装H,则G1会找到可存储的连续H分区。为了找到连续的H区域,有时是必须启动完整的GC。

  G1收集器的工作过程主要包括4个阶段:年轻GC,并发标签周期,混合GC,全GC。

  2.7.2.1年轻的Gcyoung GC主要适用于伊甸园和幸存者。当伊甸园区域的空间耗尽时,它将触发。年轻一代垃圾收集仍然使用悬挂所有应用程序线程的方法。

  伊甸园空间的数据移至幸存者空间。如果幸存者空间还不够,那么伊甸园空间中的某些数据将直接促进到老年空间。

  幸存者区域中的数据移至新的幸存者区域,一些数据也被提升为旧空间。

  最后,伊甸园空间的数据是空的,幸存者区域的数据增加,旧区域的数据增加,GC停止工作,并且应用线程继续执行。

  Yong GC比较图:

  年轻的GC还负责维持目标的年龄,生存对象已经经历了诸如年轻人总数之类的信息。G1保持促销对象的大小及其年龄信息到年龄表,并结合年龄表格,幸存者的比例(-xx:目标库维格里拉蒂奥50%)和最大项阈值(-xx:maxteningThreshold 15)。计算合适的期限阈值。

  2.7.2.1.1记住的根对象可能是年轻一代,或者在老年时代,所以所有的物体都在老年?

  如果您完整地扫描了老年,则需要大量时间进行扫描。结果,G1引入了RSET的概念。它的全名被记住了,这是跟踪对象对对象的特定对象的引用堆。

  当每个区域初始化时,它会初始化一个RSET。该集合用于记录和跟踪其他区域,以指向该区域中对象的引用。默认情况下,每个区域将其分为多张卡,因此RSET需要记录的东西应为XX region.xx卡。

  2.7.2.2同时标记周期时,当老年的比例达到一定参数时,G1首先触发并发标记周期并发标记周期。该周期类似于CMS。这是为了减少时间的停顿。并发周期分为六个阶段:

  并发标记周期之前和之后的比较图:

  2.7.2.3混合GC下一个G1执行了一系列混合GC,也称为混合GC。在此期间,因为Yong GC和清理同时标记为G的老年区域,它被称为混合阶段。以下是混合GC执行之前和之后的示意图:

  混合的GC将继续多次,直到回收记忆,混合的GC结束,然后仅触发Yong GC。然后,由于老年的比例可以以并发标记,也可能不会标记。

  混合GC触发何时由参数确定-xx:initiaatingheapoccupancepercent = n.by默认值:45%,此参数表示:当老年人的大小计算整个桩大小时,当达到阈值时会触发。

  我们可以设置混合GCS的数量,-XX:G1MIXEDGCCOUNTTATET:默认值为8,这意味着可以将混合集合的数量设置为设置物理限制。G1是可以通过除此参数外,还应应有此参数。

  -XX:G1HEAPWASTEPERCENT:默认值为5%。每个混合收藏都被暂停。G1计算废物百分比。根据堆栈的百分比,当该集合达到参数时,新的混合集合不再被激活。悬架时间和运行时间显示指数增长时,它可以通过-XX:g1heapwastepercert提供帮助,以增加参数,但会增加参数,但是这也导致更多的分裂。

  2.7.2.4完整的GC如果您分配巨型对象在老年时找不到足够的分区,则将触发完整的GC。

  如果对象存储器分布速度太快,则当混合GC空间不足或Yong GC时,S区域和O区域将无法容纳幸存的物体,并且还将触发完整的GC。

  G1的完整GC算法与CMS相同。这是由单个线程执行的串行GC,将导致长时间的SWT。因此,有必要连续调整以避免尽可能多的全GC。

  -XX:+USEG1GC:打开G1垃圾收集器

  -XX:MAXGCPAUSEMILIS:设置预期达到的最大GC暂停指示器,默认值为200毫秒。如果任何暂停都超过此设置值,GL将尝试调整新一代和老年人的比例,请调整大小堆并调整促销年龄以尝试实现预设目标,但不能保证成功。如果暂停缩短,对于新一代而言,这意味着它可能会增加新一代GC的数量,GC将变得更加频繁。对于老年人区域,为了获得较短的停顿,混合GC时收集的区域数量也将变得更少,这无疑会增加全GC的可能性。

  -xx:g1heapriionionsize = n:G1区域集的大小。2的值在2 MB和32 MB之间。目标是根据最小的Java桩尺寸分配约2048区域,默认值为1/2000堆内存。

  -xx:ParallelGCThreads = n:设置stw工作线程数的值。设置n的值到逻辑处理器的数量。n的值与逻辑处理器的数量相同,最多为8。

  -xx:concgcthreads = n:设置并行标记的线程数,设置n到并行垃圾回收线的大约1/4。

  -xx:initiaingheapoccupancepercent = n:设置扳机并发标签周期的Java堆阈值。默认值为45,这意味着当职业率为整个Java堆的45%时,将触发并发标记周期。IF。InitiaatingHeapocupancePercent设置了太大,这将导致并发循环开始缓慢,因此全GC的可能性将大大增加。相反,少量的Initiaingheapocaccutent值将使并发周期非常频繁,并且大量的GC螺纹抓住CPUIT将导致应用程序的性能下降。

  作者:Liu Java