第五章 JVM垃圾收集器(1)
2016-02-05 22:15
246 查看
说明:垃圾回收算法是理论,垃圾收集器是回收算法的实现,关于回收算法,见《第四章 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:
View Code
适用场合:
很多的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来指定当年老代空间满了多少后进行垃圾回收
标记-清理算法:会产生内存碎片,由于是在老年代,可能会提前触发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的四种情况
旧生代空间不足
不要创建过大的对象获数组
尽量让对象在minor GC被回收
让对象在年轻代多存活一段时间,可能这段时间内就会被minor GC回收
方法区满了
增大方法区
使用CMS GC回收方法区
CMS GC中promotion failed(minor GC时,survivor区放不下,年老区也放不下)和concurrent mode failure
增大survivor区
增大年老区
调低-XX:CMSInitiatingOccupancyFraction
设置:-XX:CMSMaxAbortablePrecleanTime=5(单位:ms),防止CMS在重新标记很久后才进行并发清理
空间担保机制(这一块儿见《深入理解Java虚拟机(第二版)》P98)
附:具体的配置参数查看《深入理解Java虚拟机(第二版)》P90
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:
<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>
View Code
适用场合:
很多的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来指定当年老代空间满了多少后进行垃圾回收
标记-清理算法:会产生内存碎片,由于是在老年代,可能会提前触发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的四种情况
旧生代空间不足
不要创建过大的对象获数组
尽量让对象在minor GC被回收
让对象在年轻代多存活一段时间,可能这段时间内就会被minor GC回收
方法区满了
增大方法区
使用CMS GC回收方法区
CMS GC中promotion failed(minor GC时,survivor区放不下,年老区也放不下)和concurrent mode failure
增大survivor区
增大年老区
调低-XX:CMSInitiatingOccupancyFraction
设置:-XX:CMSMaxAbortablePrecleanTime=5(单位:ms),防止CMS在重新标记很久后才进行并发清理
空间担保机制(这一块儿见《深入理解Java虚拟机(第二版)》P98)
附:具体的配置参数查看《深入理解Java虚拟机(第二版)》P90
相关文章推荐
- 数据集参数取值构件
- HDU-1253 胜利大逃亡 (BFS)
- junit4X系列--Builder、Request与JUnitCore
- iOS-对话框的应用
- java中基本类型的参数传递和引用类型的参数传递
- 安卓开发——详解camera.rotate(x,y,z);的旋转方向
- junit4X系列--Builder、Request与JUnitCore
- C 封装一个通用链表 和 一个简单字符串开发库
- 基于OpenWrt的PPTP插件开启防火墙转发
- poj 2079 Triangle(旋转卡壳)
- junit4X系列--Rule
- Codeforces 514E 矩阵快速幂
- junit4X系列--Rule
- [原创][LaTex]汇总博文
- uva 10859 树形dp
- HDU2824 The Euler function(欧拉函数)
- LeetCode322. Coin Change
- 接口1
- jQuery2(JQuery实现onload)
- 理解javascript中所有的函数参数是按值传递