JVM第七篇(垃圾回收机制二)

在上篇文章,介绍了三种垃圾回收的算法,在实际的JVM中,三种算法都有所应用。通过分代的垃圾回收机制,来使得三种垃圾回收算法能够协同工作。

将堆内存划分为两个区域,新生代和老年代。
新生代又分为三个区域,伊甸园,幸存区from和幸存区to。
新生代中主要存放不经常使用的对象,用完就可以进行垃圾回收,而老年代中主要存放经常使用的对象,用于长时间的保存。
新生代中经常进行垃圾回收,而老年代很久才会进行一次垃圾回收。针对不同的区域,采用不同的垃圾回收算法。
请添加图片描述
分代垃圾回收工作流程:

  1. 当对象被创建时,首先存放在伊甸园中,当伊甸园中空间不足,新创建的对象存放不下,则触发一次新生代垃圾回收,Minor GC,Minor GC首先找到可以被回收的对象,将其垃圾回收,然后将幸存的对象,存放到幸存区to,然后将幸存对象的寿命+1(寿命就是经历垃圾回收的次数)。最后将幸存区from和to交换位置。
  2. 新对象继续放入伊甸园中,当新生代内存不足,再一次触发MinorGC,将伊甸园和幸存区from对象进行垃圾回收,然后将幸存的对象放入幸存区to,交互from和to的位置,在MinorGC中如果发现幸存对象的寿命达到阈值(阈值为15),则将其移入到老年代中。
  3. 当新生代中内存不足,触发MinorGC,垃圾回收后,尝试将寿命达到阈值的对象,放入老年代中,发现老年代中内存也已经不足,则触发一次Full GC。Full GC会将新生代和老年代中的对象做一次垃圾回收。
  4. 当Full GC 完成之后,发现还是没有内存,将会抛出一个 OutOfMemoryError:Java heap space

当进行垃圾回收时,会将用户程序的线程停止,Stop the world。MinorGC 和 Full GC都将会暂停用户程序的线程。

相关的VM参数:
请添加图片描述
垃圾回收器:
分为三类,串行,吞吐量优先,响应时间优先。
在进行垃圾回收时,会暂停其它用户进程,stop the world,这段时间称为STW时间
串行:
是一个单线程的垃圾回收器,在垃圾回收时,暂停其它的线程。适合堆内存较小的情况,cpu核数少的情况。
吞吐量优先:
是一个多线程的垃圾回收器,适合堆内存较大的情况,cpu核数较多的情况。
吞吐量优先是在单位时间内,尽可能使 STW时间最短(单位时间内STW时间最短)。
响应时间优先:
是一个多线程的垃圾回收器,适合堆内存较大的情况,cpu核数较多的情况。响应时间优先尽可能的让单次STW时间最短。

串行方式:
串行方式使用的是 Serial 的垃圾回收器,只有一个垃圾回收线程。
开启串行方式的VM参数语句 : -XX:+UseSerialGC = Serial + SerialOld
串行方式,分为两个部分,Serial和 SerialOld,Serial 工作在新生代,采用的是复制算法进行垃圾回收,SerialOld是工作在老年代,采用标记整理算法进行垃圾回收。
请添加图片描述
在串行垃圾回收器进行工作的时候,只有一个垃圾回收线程,在进行垃圾回收之前,将用户的其它线程阻塞,等待垃圾回收线程完成垃圾回收。在完成垃圾回收之后,将被阻塞的用户线程唤醒,继续运行。

吞吐量优先:
吞吐量优先采用的是Parallel的垃圾回收器,是多个垃圾回收线程并行执行的。
开启吞吐量优先垃圾回收器的VM参数(只有开启其中一个,自动开启另一个,在JDK1.8中自动开启)
-XX:+UseParallelGC (新生代的垃圾回收器,采用复制算法)
-XX:+UseParallelOldGC(老年代的垃圾回收器,采用标记整理法)

-XX:+UseAdaptiveSizePolicy(动态的调整新生代中伊甸园和幸存区的比例,堆的大小)

-XX:GCTimeRatio=ratio(调整吞吐量的目标,计算公式 1/(1+ration)值为垃圾回收时间的占比 )
例:默认值 ration为 99 ,根据公式 值为 0.01,即垃圾回收的时间为占总时间的 0.01 ,如果垃圾回收时间达不到这个比例,将会自动调整堆的大小,以达到这个比例。

-XX:MaxGCPauseMillis=ms(设置最大暂停时间,即垃圾回收的最大时间)
-XX:ParallelGCThreads=n(设置垃圾回收的线程数)请添加图片描述
在垃圾回收之前,暂停所有用户的程序线程,启动多个垃圾回收线程,以最快的速度完成垃圾回收,然后启动暂停的用户程序线程。

响应时间优先:
响应时间优先使用的是 ConcMarkSweep(CMS) 的垃圾回收器,CMS垃圾回收器可以在垃圾回收的部分阶段,和用户线程进行并发(同时)执行,采用的垃圾回收算法是标记整理算法。并发就是在垃圾回收线程工作的同时,用户线程可以正常执行。
CMS是工作在老年代的垃圾回收器,在有的时候,CMS的垃圾回收线程会存在并发失败的情况,这时会采用SerialOld作为老年代的垃圾回收器。
ParNew是工作在新生代的垃圾回收器,采用的垃圾回收算法是复制算法。

开启CMS的VM参数语句 :
-XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld

-XX:ParallelGCThreads=n (设置并行的线程数,包括用户线程和垃圾回收线程,下图中为 4,包含三个用户线程与一个垃圾回收线程)
-XX:ConcGCThreads=threads(设置并发的垃圾回收线程数,下图中值为 1,只有一个垃圾回收线程)
-XX:CMSInitiatingOccupancyFraction=percent(设置内存占比的值。达到值则执行垃圾回收)
-XX:+CMSScavengeBeforeRemark(设置在重新标记之前,对新生代做一次垃圾回收工作)

下面是CMS垃圾回收器的工作流程:
请添加图片描述

  1. 在老年代发生内存不足是,会执行一个初始标记动作,这时候会暂停其它所有用户进程,初始标记只标记根对象
  2. 标记完成之后,用户线程和垃圾回收线程就可以并发执行,垃圾回收线程会将所有需要被垃圾回收的对象标记出来。
  3. 在并发标记完成之后,还需要重新标记,因为并发标记时,用户线程也在执行,可能会影响到对象的引用,需要重新标记,重新标记不能与用户线程并发执行。
  4. 在完成重新标记之后,垃圾回收线程就可以进行清理工作,此时可以与用户线程并发执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值