JVM垃圾收集器(1)

此文已由作者赵计刚薪授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

说明:垃圾回收算法是理论,垃圾收集器是回收算法的实现,关于回收算法,见《第四章 JVM垃圾回收算法

1、七种垃圾收集器

  • Serial(串行GC)-- 复制
  • ParNew(并行GC)-- 复制
  • Parallel Scavenge(并行回收GC)-- 复制
  • Serial Old(MSC)(串行GC)-- 标记-整理
  • CMS(并发GC)-- 标记-清除
  • Parallel Old(并行GC)--标记-整理
  • G1(JDK1.7update14才可以正式商用)

说明:

  • 1~3用于年轻代垃圾回收:年轻代的垃圾回收称为minor GC
  • 4~6用于年老代垃圾回收(当然也可以用于方法区的回收):年老代的垃圾回收称为full GC
  • G1独立完成"分代垃圾回收"

注意:并行与并发

  • 并行:多条垃圾回收线程同时操作
  • 并发:垃圾回收线程与用户线程一起操作

2、常用五种组合

  • Serial/Serial Old
  • ParNew/Serial Old:与上边相比,只是比年轻代多了多线程垃圾回收而已
  • ParNew/CMS:当下比较高效的组合
  • Parallel Scavenge/Parallel Old:自动管理的组合
  • G1:最先进的收集器,但是需要JDK1.7update14以上

2.1、Serial/Serial Old:


特点:

  • 年轻代Serial收集器采用单个GC线程实现"复制"算法(包括扫描、复制)
  • 年老代Serial Old收集器采用单个GC线程实现"标记-整理"算法
  • Serial与Serial Old都会暂停所有用户线程(即STW)

说明:

  • STW(stop the world):编译代码时为每一个方法注入safepoint(方法中循环结束的点、方法执行结束的点),在暂停应用时,需要等待所有的用户线程进入safepoint,之后暂停所有线程,然后进行垃圾回收。

适用场合:

  • CPU核数<2,物理内存<2G的机器(简单来讲,单CPU,新生代空间较小且对STW时间要求不高的情况下使用)
  • -XX:UseSerialGC:强制使用该GC组合
  • -XX:PrintGCApplicationStoppedTime:查看STW时间

2.2、ParNew/Serial Old:


说明:

  • ParNew除了采用多GC线程来实现复制算法以外,其他都与Serial一样,但是此组合中的Serial Old又是一个单GC线程,所以该组合是一个比较尴尬的组合,在单CPU情况下没有Serial/Serial Old速度快(因为ParNew多线程需要切换),在多CPU情况下又没有之后的三种组合快(因为Serial Old是单GC线程),所以使用其实不多。
  • -XX:ParallelGCThreads:指定ParNew GC线程的数量,默认与CPU核数相同,该参数在于CMS GC组合时,也可能会用到

2.3、Parallel Scavenge/Parallel Old:


特点:

  • 年轻代Parallel Scavenge收集器采用多个GC线程实现"复制"算法(包括扫描、复制)
  • 年老代Parallel Old收集器采用多个GC线程实现"标记-整理"算法
  • Parallel Scavenge与Parallel Old都会暂停所有用户线程(即STW)

说明:

  • 吞吐量:CPU运行代码时间/(CPU运行代码时间+GC时间)
  • CMS主要注重STW的缩短(该时间越短,用户体验越好,所以主要用于处理很多的交互任务的情况)
  • Parallel Scavenge/Parallel Old主要注重吞吐量(吞吐量越大,说明CPU利用率越高,所以主要用于处理很多的CPU计算任务而用户交互任务较少的情况)

参数设置:

  • -XX:+UseParallelOldGC:使用该GC组合
  • -XX:GCTimeRatio:直接设置吞吐量大小,假设设为19,则允许的最大GC时间占总时间的1/(1+19),默认值为99,即1/(1+99)
  • -XX:MaxGCPauseMillis:最大GC停顿时间,该参数并非越小越好
  • -XX:+UseAdaptiveSizePolicy:开启该参数,-Xmn/-XX:SurvivorRatio/-XX:PretenureSizeThreshold这些参数就不起作用了,虚拟机会自动收集监控信息,动态调整这些参数以提供最合适的的停顿时间或者最大的吞吐量(GC自适应调节策略),而我们需要设置的就是-Xmx,-XX:+UseParallelOldGC或-XX:GCTimeRatio两个参数就好(当然-Xms也指定上与-Xmx相同就好)

注意:

  • -XX:GCTimeRatio和-XX:MaxGCPauseMillis设置一个就好
  • 不开启-XX:+UseAdaptiveSizePolicy,-Xmn/-XX:SurvivorRatio/-XX:PretenureSizeThreshold这些参数依旧可以配置,以resin服务器为例

                <jvm-arg>-Xms2048m</jvm-arg>
                <jvm-arg>-Xmx2048m</jvm-arg>
                <jvm-arg>-Xmn512m</jvm-arg>
                <jvm-arg>-Xss1m</jvm-arg>
                <jvm-arg>-XX:PermSize=256M</jvm-arg>
                <jvm-arg>-XX:MaxPermSize=256M</jvm-arg>
                <jvm-arg>-XX:SurvivorRatio=8</jvm-arg>
                <jvm-arg>-XX:MaxTenuringThreshold=15</jvm-arg>
    
                <jvm-arg>-XX:+UseParallelOldGC</jvm-arg>
                <jvm-arg>-XX:GCTimeRatio=19</jvm-arg>
    
                <jvm-arg>-XX:+PrintGCDetails</jvm-arg>
                <jvm-arg>-XX:+PrintGCTimeStamps</jvm-arg>

适用场合:

  • 很多的CPU计算任务而用户交互任务较少的情况
  • 不想自己去过多的关注GC参数,想让虚拟机自己进行调优工作

2.4、ParNew/CMS


说明:

  • 以上只是年老代CMS收集的过程,年轻代ParNew看"2.2、ParNew/Serial Old"就好
  • CMS是多回收线程的,不要被上图误导,默认的线程数:(CPU数量+3)/4
  • CMS主要注重STW的缩短(该时间越短,用户体验越好,所以主要用于处理很多的交互任务的情况)

特点:

  • 年轻代ParNew收集器采用多个GC线程实现"复制"算法(包括扫描、复制)
  • 年老代CMS收集器采用多线程实现"标记-清除"算法
    • 初始标记:标记与根集合节点直接关联的节点。时间非常短,需要STW
    • 并发标记:遍历之前标记到的关联节点,继续向下标记所有存活节点。时间较长。
    • 重新标记:重新遍历trace并发期间修改过的引用关系对象。时间介于初始标记与并发标记之间,通常不会很长。需要STW
    • 并发清理:直接清除非存活对象,清理之后,将该线程占用的CPU切换给用户线程
  • 初始标记与重新标记都会暂停所有用户线程(即STW),但是时间较短;并发标记与并发清理时间较长,但是不需要STW

关于并发标记期间怎样记录发生变动的引用关系对象,在重新标记期间怎样扫描这些对象,见《第六章 JVM垃圾收集器(2)

缺点:

  • 并发标记与并发清理:按照说明的第二点来讲,假设有2个CPU,那么其中有一个CPU会用于垃圾回收,而另一个用于用户线程,这样的话,之前是两CPU运行用户线程,现在是一个,那么效率就会急剧下降。也就是说,降低了吞吐量(即降低了CPU使用率)。
  • 并发清理:在这一过程中,产生的垃圾无法被清理(因为发生在重新标记之后)
  • 并发标记与并发清理:由于是与用户线程并发的,所以用户线程可能会分配对象,这样既可能对象直接进入年老代(例如,大对象),也可能进入年轻代后,年轻代发生minor GC,这样的话,实际上要求我们的年老代需要预留一定空间,也就是说要在年老代还有一定空间的情况下就要进行垃圾回收,留出一定内存空间来供其他线程使用,而不能等到年老代快爆满了才进行垃圾回收,通过-XX:CMSInitiatingOccupancyFraction来指定当年老代空间满了多少后进行垃圾回收,如果在回收过程中,老年代已经不够使用了,这时候CMS回收失败,老年代使用serial Old进行GC
  • 标记-清理算法:会产生内存碎片,由于是在老年代,可能会提前触发Full GC(这正是我们要尽量减少的)

参数设置:

  • -XX:+UseConcMarkSweepGC:使用该GC组合
  • -XX:CMSInitiatingOccupancyFraction:指定当年老代空间满了多少后进行垃圾回收
  • -XX:+UseCMSCompactAtFullCollection:(默认是开启的)在CMS收集器顶不住要进行FullGC时开启内存碎片整理过程,该过程需要STW
  • -XX:CMSFullGCsBeforeCompaction:指定多少次FullGC后才进行整理
  • -XX:ParallelCMSThreads:指定CMS回收线程的数量,默认为:(CPU数量+3)/4

适用场合:

  • 用于处理很多的交互任务的情况
  • 方法区的回收一般使用CMS,配置两个参数:-XX:+CMSPermGenSweepingEnabled与-XX:+CMSClassUnloadingEnabled

3、一些经验

  • 由于当下大型企业用的比较多的还是jdk1.6版本,所以G1用的还是不多
  • 用得最多的两种:ParNew/CMS和Parallel Scavenge/Parallel Old
  • Full GC的四种情况
    • 增大survivor区
    • 增大年老区
    • 调低-XX:CMSInitiatingOccupancyFraction
    • 设置:-XX:CMSMaxAbortablePrecleanTime=5(单位:ms),防止CMS在重新标记很久后才进行并发清理
    • 增大方法区
    • 使用CMS GC回收方法区
    • 不要创建过大的对象获数组
    • 尽量让对象在minor GC被回收
    • 让对象在年轻代多存活一段时间,可能这段时间内就会被minor GC回收
    • 旧生代空间不足
    • 方法区满了
    • CMS GC中promotion failed(minor GC时,survivor区放不下,年老区也放不下)和concurrent mode failure
    • 空间担保机制(这一块儿见《深入理解Java虚拟机(第二版)》P98)

附:具体的配置参数查看《深入理解Java虚拟机(第二版)》P90

免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 git常用命令
【推荐】 Hadoop单机/伪分布式集群搭建(新手向)
【推荐】 iOS 安装包瘦身(下篇)

原文地址:https://www.cnblogs.com/163yun/p/10078095.html

时间: 2024-10-07 20:04:26

JVM垃圾收集器(1)的相关文章

第六章 JVM垃圾收集器(2)

上一章记录了几种常见的垃圾收集器,见<第五章 JVM垃圾收集器(1)> 1.G1 说明: 从上图来看,G1与CMS相比,仅在最后的"筛选回收"部分不同(CMS是并发清除),实际上G1回收器的整个堆内存的划分都与其他收集器不同. CMS需要配合ParNew,G1可单独回收整个空间 原理: G1收集器将整个堆划分为多个大小相等的Region G1跟踪各个region里面的垃圾堆积的价值(回收后所获得的空间大小以及回收所需时间长短的经验值),在后台维护一张优先列表,每次根据允许的

JVM垃圾收集器

1.垃圾回收器类型 1.串行垃圾回收器(Serial Garbage Collector) 2. 并行垃圾回收器(Parallel Garbage Collector) 3. 并发标记扫描垃圾回收器(CMS Garbage Collector) 4. G1垃圾回收器(G1 Garbage Collector) 1.串行垃圾回收器(Serial Garbage Collector) 串行垃圾回收器通过持有应用程序所有的线程进行工作.它为单线程环境设计,只使用一个单独的线程进行垃圾的回收,通过冻结所

【006】【JVM——垃圾收集器总结】

 JVM--垃圾收集器总结 垃圾收集器概览 收集算法是内存回收的方法论,垃圾收集据是内存回收的具体实现.Java虚拟机规范中对垃圾收集器应该如何实现没有规定,不同的厂商.不同版本的虚拟机所提供的垃圾收集器可能会有很大差别,一般都会提供参数供用户根据自己的所用特点和要求组合出各个年代所使用的收集器.下面是基于JDK 1.7 Update 14 之后的HotSpot 虚拟机垃圾收集器.如果两个收集器之间有连线就说明它们可以搭配使用.直到现在还没有最好的收集器,更加设有万能的收集器,只是对具体应用

JVM垃圾收集器-Parallel Scavenge收集器

今天我给大家讲讲JVM垃圾收集器-Parallel Scavenge收集器 Parallel Scavenge收集器 ? ? ? ?Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器,看上去和ParNew都一样,那它有什么特别之处呢? ? ? ??Parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标是

5种JVM垃圾收集器特点和8种JVM内存溢出原因

先来看看5种JVM垃圾收集器特点 一.常见垃圾收集器 现在常见的垃圾收集器有如下几种: 新生代收集器: Serial ParNew Parallel Scavenge 老年代收集器: Serial Old CMS Parallel Old 堆内存垃圾收集器:G1 每种垃圾收集器之间有连线,表示他们可以搭配使用. 二.新生代垃圾收集器 (1)Serial 收集器 Serial 是一款用于新生代的单线程收集器,采用复制算法进行垃圾收集.Serial 进行垃圾收集时,不仅只用一条线程执行垃圾收集工作,

记一次有关于Jvm垃圾收集器的整理

记一次有关于Jvm垃圾收集器的整理 垃圾回收器 算法: 引用计数法 复制算法 标记清楚 标记整理 垃圾回收的方式 1.Serial:串行回收 2.Parallel:并行回收 3.CMS:并发标记清除 4.G1:G1 截止到java10               之后有ZGC Seial:串行垃圾回收,单线程垃圾回收的时候会停掉用户的线程进行垃圾回收不适合服务器的环境 Parallel:并行垃圾回收多个垃圾收集线程并行工作也会停掉垃圾回收的时候用户的线程 CMS:用户线程和垃圾回收线程同时执行(

jvm 垃圾收集器分析

jvm 垃圾收集器分析 jvm 垃圾收集器分析   新生代收集器 老年代收集器 优点 缺点 serial收集器 V   1.jdk1.3开始的单线程收集器 2.client模式下很好的选择. 3.复制算法 1.单线程,收集时需要暂停所有线程(stop the world) parNew收集器 V   1.serial的多线程版 2.server模式下 3.可与CMS收集器工作 4.线程数与cpu数相同 1.单CPU下不会比serial收集器性能好   Parallel Scavenge 收集器

深入了解JVM垃圾收集器

程序计数器.JVM栈.本地方法栈这三个内存区域和线程是一一对应的,并且每一个线程的这三个区域相互独立互不干扰.他们都随着线程的产生而产生,线程的灭亡而灭亡.JVM栈和本地方法栈中的栈帧都随着方法的加载而入栈,随着方法的结束而出栈. 栈帧的大小是在程序员写类的时候就确定下来的.因此这三种区域的内存大小都具备确定性,当方法结束或线程结束后,这些内存空间就会自动被回收掉,所以JVM无需考虑这些区域的内存回收问题. 堆内存和方法区的内存分配和回收就不一样了,因为一个接口中的多个实现类所需要的内存可能不一

【JVM】JVM垃圾收集器、垃圾收集算法、无用对象

Java 常见的垃圾收集器有哪些 实际上,垃圾收集器(GC,Garbage Collector)是和具体 JVM 实现紧密相关的,不同厂商(IBM.Oracle),不同版本的JVM,提供的选择也不同.接下来,我来谈谈最主流的 Oracle JDK. Serial GC 它是最古老的垃圾收集器,"Serial"体现在其收集工作是单线程的,并且在进 行垃圾收集过程中,会进入臭名昭著的"Stop-The-World"状态.当然,其单线程设计也意味着精简的 GC 实现,无需