jvm垃圾收集-java GC

转自:jvm系列(三)
JVM内存模型

GC算法:

  • 标记-清除(碎片化,大对象空间不足;效率低)
  • 复制(浪费50%的空间;持续复制长生存期对象,效率低)
  • 标记-整理(将存活对象,全部移动到一端,从此端的边界开始清除所有对象)
  • 分代收集
    所谓分代,来源于数据的存活时间,对于存活时间短的称为新生代,对于存活时间长的会将其存储到老年代,常量等则存储在持久代。
    而对于不同的区域根据其存储特性而采用与之适合的收集算法,就是分代收集。
    新生代用“复制”算法,老年代用“标记-整理”
    新生代中只有少量对象存活,采用复制算法,所费空间并不多。
    老年代中对象存活率高,对象生命周期长,不宜采用复制算法
    标记清除算法示意图:标记-清除
    复制算法示意图:
    复制为何看不到图片的标题?
    标记-整理算法示意图:
    text

垃圾收集器

衡量垃圾收集器的主要参数:STW(Stop The World event)的停顿时长,碎片化。

  • serial(单一线程串行;分代收集算法)
  • ParNew(针对新生代,多线程并行GC,采用Coping算法;分代收集算法)
  • Parallel(新生代多线程并行,老年代单线程串行,分代收集算法)
    但是提供参数,支持自适应调节策略,JVM可以根据当前系统的运行状况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间
  • Parallel Old(针对老年代,多线程并行;分代收集算法)
  • CMS(针对老年代,Concurrent Mark Sweep,标记-清除算法)
    新生代仍采用ParNew,多线程并行,copying算法;
    老年代分4个阶段,采用mark-sweep算法
    老年代的垃圾收集分:初始标记(停服,快速)->并发标记(不停服,长时)->重新标记(停服,短时)->并发清理->碎片整理(停服,时间较长)几个阶段
    因为采用的是Mark-sweep算法,因此会产生大量碎片。数次清理后,需要进行一次碎片整理。
    虽然碎片整理阶段停顿时间较长,但是耗时最长的并发标记和并发清除阶段,均不需停顿,用户线程和垃圾收集线程可以并行工作,所以整体可以说,CMS线程的内存回收过程与用户线程是并行执行的。
  • G1 (Mark-Compact算法,无碎片;可预测停顿时间;不再分代收集;JDK11默认使用)
    逻辑上还有新生代和老年代的概念,但是物理上并不再分隔。因为新生代不再采用copying算法,而是和老年代同样采用Mark-Compact算法,因此无需单独分给其一片空间进行复制。
    采用G1的JVM的堆内存,会被划分为多个大小相同的独立区域Regions(大小为1M~32M,最多不超过2000个),每个Region动态地在逻辑上被划分为Young Generation、Old Generation、Recently Copied in Young Generation、Recently Copied in Old Generation
    G1分以下步骤:
    1. 只对新生代,进行初始标记(STW),并触发一次Mitor GC
    2. 回收survivor区,将其中仍生存的对象,移动整理至Old Gen
    3. 在整个堆,并发标记(无STW),计算每个Region的对象的存活比例,如果整个Region都没有存活的对象,则立刻回收整个Region。
    4. 再标记(短暂STW),用来标记并发标记阶段时用户线程产生的新垃圾,
    5. copy/clean up(有STW),将要回收的Region中的存活对象copy到新的Region中去,然后并发清空要回收的Region,并将其返回到空闲区域链表中。存活对象copy至的Region即为Recently Copied in Young/Recently Copied in Old Generation
      Serial
      parNew
      CMS
      G1-垃圾回收后

常用的收集器组合

新生代GC策略年老代GC策略说明
serialserialGC时暂停所有应用线程
serialCMSGC时大部分时间GC线程和应用线程可并行进行
parNewCMS使用-XX:+UseParNewGC选项来开启;可以使用-XX:ParallelGCThreads选项指定parNew GC的线程数,默认为CPU核数
G1G1-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC #开启
-XX:MaxGCPauseMillis =50 #暂停时间目标
-XX:GCPauseIntervalMillis =200 #暂停间隔目标
-XX:+G1YoungGenSize=512m #年轻代大小
-XX:SurvivorRatio=6 #幸存区比例

其它

FullGC

FullGC这个概念,并非和某个确定的垃圾收集器关联,而是不论是哪个版本的JDK,采用的哪种类型的收集器,只要对老年代 Old Gen 进行了垃圾回收,那么每次对Old Gen 回收时,每stop the world一次,就算作一次 FullGC。
作用于Old Gen 的垃圾收集器,包括Serial Old、ParOld、CMS、G1四种,其中CMS在初次标记、重新标记阶段,均会有STW,因此一次CMS垃圾回收就会对full GC的times+2。

  1. Full GC == Major GC指的是对老年代/永久代的stop the world的GC

  2. Full GC的次数 = 老年代GC时 stop the world的次数

  3. Full GC的时间 = 老年代GC时 stop the world的总时间

  4. CMS 不等于Full GC,我们可以看到CMS分为多个阶段,只有stop the world的阶段被计算到了Full GC的次数和时间,而和业务线程并发的GC的次数和时间则不被认为是Full GC。但是当CMS GC 发生concurrent mode fail后,会采用备用的Serial Old GC,这种GC的 stop the world时间较之CMS相当长,一般为秒级。

  5. Full GC本身不会先进行Minor GC,我们可以配置,让Full GC之前先进行一次Minor GC,因为老年代很多对象都会引用到新生代的对象,先进行一次Minor GC可以提高老年代GC的速度。比如老年代使用CMS时,设置CMSScavengeBeforeRemark优化,让CMS remark之前先进行一次Minor GC。

查看当前JVM采用的何种GC

java -XX:+PrintCommandLineFlagsjvm参数可查看默认设置收集器类型

java -XX:+PrintGCDetails亦可通过打印的GC日志的新生代、老年代名称判断

参数解读

-XX:+UseParallelGC
-XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值