此文已由做者赵计刚薪受权网易云社区发布。html
欢迎访问网易云社区,了解更多网易技术产品运营经验。java
说明:垃圾回收算法是理论,垃圾收集器是回收算法的实现,关于回收算法,见《第四章 JVM垃圾回收算法》git
一、七种垃圾收集器算法
Serial(串行GC)-- 复制数组
ParNew(并行GC)-- 复制安全
Parallel Scavenge(并行回收GC)-- 复制服务器
Serial Old(MSC)(串行GC)-- 标记-整理多线程
CMS(并发GC)-- 标记-清除并发
Parallel Old(并行GC)--标记-整理jvm
G1(JDK1.7update14才能够正式商用)
说明:
1~3用于年轻代垃圾回收:年轻代的垃圾回收称为minor GC
4~6用于年老代垃圾回收(固然也能够用于方法区的回收):年老代的垃圾回收称为full GC
G1独立完成"分代垃圾回收"
注意:并行与并发
并行:多条垃圾回收线程同时操做
并发:垃圾回收线程与用户线程一块儿操做
二、经常使用五种组合
Serial/Serial Old
ParNew/Serial Old:与上边相比,只是比年轻代多了多线程垃圾回收而已
ParNew/CMS:当下比较高效的组合
Parallel Scavenge/Parallel Old:自动管理的组合
G1:最早进的收集器,可是须要JDK1.7update14以上
2.一、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.二、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.三、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.四、ParNew/CMS
说明:
以上只是年老代CMS收集的过程,年轻代ParNew看"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
三、一些经验
因为当下大型企业用的比较多的仍是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 安装包瘦身(下篇)