当前位置: 首页 > 后端技术 > Java

【JVM知识汇总-4】HotSpot垃圾收集器

时间:2023-04-01 18:47:14 Java

【JVM知识汇总-1】JVM内存模型【JVM知识汇总-2】HotSpot虚拟机对象【JVM知识汇总-3】垃圾收集策略与算法【JVM知识汇总-4]HotSpot垃圾收集器【JVM知识汇总-5】内存分配与回收策略【JVM知识汇总-6】JVM性能调优【JVM知识汇总-7】Class文件结构【JVM知识汇总-8】类【JVM知识汇总-9]类加载过程[JVM知识总结-10]类加载器HotSpot虚拟机提供了多种垃圾收集器,每一种都有自己的特点,虽然我们需要针对每一种收集器进行具体比较,但并不是要挑一个最好的收藏家。我们只为特定应用选择最合适的收集器。新一代垃圾收集器(单线程)串行垃圾收集器(单线程)只启动一个GC线程进行垃圾收集,垃圾收集时停止所有用户线程,即StopTheWorld。通常,客户端应用程序需要的内存较少,不会创建过多的对象,堆内存较小,因此垃圾收集器回收的时间较短。即使在此期间停止所有用户线程,也不会有明显的滞后。所以串行垃圾收集器适合客户端使用。由于Serial收集器只使用一个GC线程,避免了线程切换的开销,简单高效。ParNew垃圾收集器(多线程)ParNew是Serial的多线程版本。垃圾清理由多个GC线程并行执行。但是清理过程仍然需要StopTheWorld。ParNew追求低停顿时间。与Serial的唯一区别是它使用多线程进行垃圾收集。在多CP??U环境下,性能相比Serial会有一定程度的提升;但是线程切换需要额外的开销,所以在单线CPU环境下它的性能不如Serial。.ParallelScavenge垃圾收集器(多线程)ParallelScavenge与ParNew一样,是一个多线程的新一代垃圾收集器。但两者有巨大的区别:ParallelScavenge:追求CPU吞吐量,能在短时间内完成指定任务,适合后台无交互计算。ParNew:追求减少用户停顿时间,适合交互式应用。吞吐量=运行用户代码的时间/(运行用户代码的时间+垃圾收集时间)追求高吞吐量可以通过减少GC花费在实际工作上的时间来实现,但是,仅偶尔运行GC意味着每当GC运行时会有很多工作要做,所以这段时间堆积在堆内存中的对象数量很高。单个GC需要更多时间才能完成,从而导致更长的暂停时间。鉴于暂停时间短,最好频繁运行GC,以便它快速完成,这反过来会导致吞吐量下降。通过参数-XX:GCTimeRadio设置垃圾回收时间占总CPU时间的百分比。通过参数-XX:MaxGCPauseMillis设置垃圾处理过程的最大停顿时间。通过命令-XX:+UseAdaptiveSizePolicy启用自适应策略。只要我们设置堆的大小和MaxGCPauseMillis或GCTimeRadio,收集器就会自动调整新生代的大小,Eden与Survivor的比例,以及对象进入老年代的年龄,从而达到尽可能接近我们设置的MaxGCPauseMillis或GCTimeRadio。OldGenerationGarbageCollectorSerialOldGarbageCollector(单线程)SerialOld收集器是Serial的老年代版本。它们都是单线程收集器。只开启一个GC线程,都适合客户端应用。它们唯一的区别是:SerialOld工作在老年代,使用“标记-排序”算法;新生代连载作品,采用“复制”算法。ParallelOldGarbageCollector(多线程)ParallelOldcollector是ParallelScavenge的老版本,追求CPU吞吐量。CMSGarbageCollectorCMS(ConcurrentMarkSweep,并发标记清除)收集器是一种旨在获得最短恢复停顿时间(追求低停顿)的收集器。它在垃圾回收时由用户线程和GC线程并发执行,因此用户在垃圾回收过程中不会感觉到明显的滞后。初始标记:StopTheWorld,只使用一个初始标记线程标记所有与GCRoots直接关联的对象。并发标记:使用多个标记线程与用户线程并发执行。此过程执行可达性分析并在那里标记所有过时的对象。非常慢。重标记:StopTheWorld,使用多个标记线程并发执行,将刚才并发标记过程中出现的丢弃对象标记出来。并发清除:只使用一个GC线程与用户线程并发执行,清除刚刚标记的对象。这个过程非常耗时。并发标记和并发清除过程耗时最长,可以与用户线程一起工作。因此,一般情况下,CMS收集器的内存回收过程是与用户线程并发执行的。对于空间碎片的问题,可以开启-XX:+UserCMSCompartAtFullCollection,每次FullGC完成后,会进行一次内存压缩,将零散的对象整理成一块。设置参数-XX:CMSFullGCsBeforeCompaction,告诉CMS在N次FullGC之后,进行一次内存整合。G1通用垃圾收集器G1是用于服务器端应用程序的垃圾收集器。它没有新生代和老年代的概念,而是将堆划分为独立的区域。当要进行垃圾回收时,首先估计每个Region的垃圾量,每次都从垃圾回收值最大的Region开始回收,这样可以获得最大的回收效率。整体来说,G1是一个基于“mark-sort”算法实现的收集器,在本地(两个Region之间)是基于“copy”算法实现的,也就是说在运行过程中不会产生内存空间碎片。[思考]一个对象与其内部引用的对象可能不在同一个Region中,那么垃圾回收时是否需要扫描整个堆内存来进行完整的可达性分析?【解决】不需要!每个Region只有一个RememberedSet,用于记录本区域内所有对象引用的对象所在的区域。在进行可达性分析时,只需将RememberedSet添加到GCRoots中,即可避免整个堆内存被破坏。遍历。如果不算维护RememberSet的操作,G1收集器的工作过程分为以下几个步骤:初始标记:StopTheWorld,只使用一个初始标记线程标记所有与GCRoots直接相关的对象。并发标记:标记线程将与用户线程并发执行。此过程执行可达性分析并且非常慢。Finalmark:StopTheWorld,适合多个标记线程并发执行。筛选回收:回收被丢弃的对象,此时也需要StopTheWorld,使用多个筛选回收线程并发执行。