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

面试官:如何调优JDK8的垃圾回收器?

时间:2023-04-01 20:31:13 Java

采访者:JDK8的垃圾收集器如何调优?看着面试官真诚的眼神,我心里想自己看着年纪不大,却问出这么直击心灵的问题。擦了擦额头上的汗,稍微调整一下紧张的心情,对面试官说:JDK8中有几个收集器,Serial收集器,Parallel收集器,CMS收集器,G1收集器,需要根据实际硬件。选择和调整配置和业务需求。如此简单的回答不能让面试官满足深度要求,当然也不能满足面试官的强烈需求。果然,面试官问:如果是桌面应用,内存占用只有100MB,应该选择哪个垃圾收集器?我的快速回答:串行收集器。看着面试官期待的眼神,我详细解释了下:Serialcollectorserialcollector是用单线程来处理所有的垃圾收集工作,因为没有多线程的额外开销,比较有效。所以最适合单核CPU环境,因为没办法发挥多核的优势。但是,当应用程序使用的内存大小在100MB左右甚至更小时,它也适用于多核CPU环境。边说边在纸上画了句:Client模式下JVM默认的垃圾收集器是Serial收集器,也可以通过JVM参数-XX:+UseSerialGC显式启用Serial收集器。面试官又问了:如果是高吞吐、大内存、多核CPU的应用,应该选择哪个垃圾收集器?我的快速回答:并行收集器。看着面试官期待的眼神,我详细解释了下:ParallelcollectorParallelcollector是一种类似于Serialcollector的分代收集器。主要区别在于垃圾回收时使用了多线程来加速垃圾回收。.因此,它更适合使用大内存和多核CPU的环境。边说边画纸:Server模式下JVM默认的垃圾收集器是Parallel收集器,也可以通过JVM参数-XX:+UseParallelGC开启。启用Parallelcollector后,默认情况下,Minorgarbagecollection(新生代垃圾回收)和Majorgarbagecollection(老年代垃圾回收)并行执行,可以进一步降低垃圾回收的开销。Parallel收集器可以指定最大垃圾收集暂停时间、吞吐量(用户代码运行时间/(用户代码运行时间+垃圾收集运行时间))以及JVM参数占用堆空间的目标值:-XX:MaxGCPauseMillis:最大垃圾回收暂停时间,单位毫秒,如:-XX:MaxGCPauseMillis=200,表示最大垃圾回收暂停时间为200毫秒。默认情况下,没有指定最大垃圾收集暂停时间。如果指定了暂停时间目标,则调整堆大小和其他与垃圾收集相关的参数,以便垃圾收集的暂停时间短于指定值。这些调整可能会导致整体应用程序吞吐量降低,或者可能无法始终满足指定的最大垃圾收集暂停时间目标。-XX:GCTimeRatio:吞吐量大小,如:-XX:GCTimeRatio=19,表示垃圾回收运行时间目标设置为1/(1+应用总运行时间(用户代码运行时间+垃圾收集运行时间)19),即5%。默认值为99,垃圾回收的目标时间占应用总运行时间的1/(1+99),即1%。-Xmx:堆占用的最大占用空间,如:-Xmx1G,表示堆占用的最大占用空间为1GB。此外,Parallel收集器还有一个隐含的目标:只要满足其他目标,就尽量减少堆内存的大小。这三个目标有优先级:高优先级:最大垃圾收集停顿时间中优先级:吞吐量目标低优先级:最小堆内存目标并行收集器自动根据指定的目标进行代大小和底层调整,尽量达到指定的目标,但是不能保证可以达到100%。面试官又问了:如果同样是一个使用大内存、多核CPU的web应用,但是要求垃圾回收停顿时间尽可能短,应该选择哪个垃圾回收器?我想了想回答:CMScollector。看着面试官期待的眼神,我详细解释了:CMS收集器CMS(ConcurrentMarkSweep)收集器是为那些要求垃圾收集停顿时间尽可能短,并且可以与垃圾共享CPU资源的应用而设计的收藏家。内存使用量比较大的应用程序和多核CPU往往更适合使用CMS收集器。您可以使用JVM参数-XX:+UseConcMarkSweepGC来启用CMS收集器。启用后,它会同时作用于Minorgarbagecollection(新生代的垃圾回收)和Majorgarbagecollection(老年代的垃圾回收)。CMS收集器尝试通过使用单独的垃圾收集器线程并发执行用户线程并跟踪可访问对象来减少主要垃圾收集引起的暂停时间。在每个主要垃圾收集周期中,CMS收集器在收集开始时暂停所有用户线程一小段时间,然后在收集中间再次暂停。第二次暂停往往是两次暂停中时间较长的一次,并且在两次暂停之间使用多个线程并行地做收集工作。因此,CMS收集器的垃圾收集过程分为以下四个步骤:初始标记(CMSinitialmark):这一步会暂停所有用户线程,但需要很短的时间来标记与GCRoot直接关联的对象。并发标记(CMSconcurrentmark):这一步耗时较长,但用户线程可以同时运行,将路径可达的对象标记到GCRoot。Remark(CMSremark):这一步会暂停所有用户线程,但耗时比较短。由于步骤2中用户线程是同步运行的,所以应该修正步骤2中用户线程同步运行产生的对象标记的变化。并发扫描(CMSconcurrentsweep):这一步耗时较长,但用户线程可以并发运行。边说边画在纸上:面试官继续问:如果堆中有超过50%的活跃对象,对象分配和对象升级的频率高,垃圾回收的停顿时间大于0.5秒,应该选择哪个垃圾收集器?我想了想回答:G1收藏家。看着面试官期待的眼神,我详细解释了一下:G1收集器G1(Garbage-First)收集器是一个主要针对服务端应用的垃圾收集器,适用于多核CPU大内存的服务器。它试图以高概率同时满足小的垃圾收集暂停时间和高吞吐量。所有与堆相关的操作(例如全局标记)都与用户线程并发运行,这避免了随着堆大小的增加而增加垃圾收集暂停时间。G1收集器是垃圾收集技术史上里程碑式的成就。跳出了以往收集整代垃圾的思维模式,开创了基于Rigion的collectorforpartialcollection和memorylayout形式的设计思路。在后续的JDK版本中,G1收集器逐渐成为CMS收集器的替代者和继承者。G1收集器虽然沿用了分代收集的设计,但是整个堆的内存设计却有明显的不同。整个堆被分成一组大小相等的独立区域(Region),每个独立区域(Region)有一个连续的虚拟内存范围,逻辑上分为年轻代的Eden区,Survivor区或旧区根据需要。时代。边说边画在纸上:通过JVM参数-XX:MaxGCPauseMillis为G1收集器指定垃圾收集的目标停顿时间,默认为200毫秒。G1收集器使用预测模型来估计在暂停时间内可以收集多少个独立区域。在垃圾收集结束时,G1收集器选择下一个要收集的区域。通常,G1收集器通过选择年轻代独立区域的数量来控制垃圾收集暂停时间。与其他垃圾收集器一样,可以通过参数指定新生代的大小,但这样做可能会影响G1收集器满足其暂停时间目标的程度。除了停顿时间目标,停顿间隔也可以通过JVM参数-XX:GCPauseIntervalMillis来指定,默认为0。她的眼中充满了钦佩。俗话说:金风玉露一遇,得天下无数人。想知道接下来会发生什么,就听下一章吧。