• jvm 05-JVM垃圾收集策略


    GC策略

    • 新生代GC策略:
      • 串行GC:Serial Copying
      • 并行回收GC:Parallel Scavenge
      • 并行GC:ParNew
    • 老年代GC策略:
      • 串行GC:Serial MSC
      • 并行GC:Parallel MSC
      • 并发GC:CMC

    新生代GC策略

    新生代--串行GC(Serial Copying)

    • 算法:复制清理算法
    • 操作步骤:
    1. 扫描新生代中所有存活的对象
    2. 使用Minor GC进行垃圾回收,同时将存活对象保存到S0 or S1区
    3. 在上一次Minor GC的基础上进行S0和S1区的角色交换
    4. 经历许多次Minor GC依然存活的对象晋升到老年代

    新生代--并行回收GC(Parallel Scavenge)

    • 算法:复制清理算法
    • 操作步骤:
      • 在扫描和复制时均采用多线程方式处理
      • 在新生代使用并行GC处理的时候会产生有一个STW(stop The World pause)的暂停,该暂停主要是进行对象回收,期间其他的线程将被暂时性挂起。
      • 并行回收GC为空间较大的新生代回收提供许多优化
      • 在多CPU的机器上,其GC耗时会比串行方式短
      • 该方式适合多CPU、对暂停时间要求较短的应用

    新生代--并行GC(ParNew)

    • 算法:复制清理算法
    • 操作步骤:
      • 并行GC必须结合老年代CMS GC一起使用。
      • 因为在新生代如果发生了Minor GC时,老年代也需要使用CMS GC同时处理
      • CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器,主要针对要求服务器响应速度快的应用

    老年代GC策略

    老年代--串行GC(Serial MSC)

    • 算法:标记-清除-压缩(Mark-Sweep-Compact)
    • 特点:串行执行的过程中为单线程,需要暂停应用并耗时较长
    • 操作步骤:
    1. 扫描老年代中还存活的对象,并且对这些对象进行标记
    2. 遍历整个老年代内存空间,回收所有未标记的对象内存
    3. 将所有存活对象都集中在一端,而后将所有回收对象的内存空间变为一块连续的内存空间

    老年代--并行GC(Parallel )

    • 算法:标记-压缩(Mark-Compact)
    • 特点:
      • 多线程同时进行垃圾回收可以缩短应用的暂停时间
      • 但是由于老年代的空间一般较大,在扫描和标记存活对象上还是需要花费较长的时间
    • 操作步骤:
    1. 将老年代内存空间按照线程个数划分为若干个子区域
    2. 多线程并行对各自子区域内的存活对象进行标记
    3. 多线程并行清除所有未标记的对象
    4. 多线程并行将多个存活对象整理在一起,并将所有回收的对象空间整合为一体

    老年代--并发GC(Concurrent Makr-Sweep GC、CMS GC )

    • 算法:标记-清除(Mark-Sweep)
    • 特点:
      • 只有在第一次和重新标记阶段才会暂停整个应用,这样对应用程序所带来的影响非常小。
      • 并发标记与回收线程会与应用线程争抢CPU资源,并且容易产生内存碎片。
    • 操作步骤:
    1. 初始标记(STW Initial Mark):虚拟机暂停正在执行的任务(STW),由根对象扫描出所有的关联对象并做出标记。此过程只会导致短暂的JVM暂停。
    2. 并发标记(Concurrent Marking):恢复所有暂停的线程对象,并且对之前标记过的对象进行扫描,取得所有跟标记对象有关联的对象。
    3. 并发预清理(Concurrent Precleaning):查找所有在并发标记阶段新进入老年代的对象(可能是从新生代晋升到老年代或被分配到老年代),通过重新扫描,减少下一阶段的工作。
    4. 重新标记(STW Remark):此阶段会暂停虚拟机,对在并发标记阶段被改变引用或新创建的对象进行标记
    5. 并发清理(Concurrent Sweeping):恢复所有暂停的应用线程,对所有未标记的垃圾对象进行清理,并且尽量将已回收对象的空间重新拼凑为一个整体。在此阶段收集器线程和应用程序线程并发执行。
    6. 并发重置(Concurrent Reset):重置CMS收集器的数据结构,等待下一次垃圾回收。

    GC参数

    GC策略调整参数

    • -XX:+UseSerialGC -- Serial Copying + Serial MSC
    • -XX:+UseParallelGC -- Parallel Scavenge + Parallel Mark Sweep
    • -XX:+UseConcMarkSweepGC -- ParNew + Concurrent Mark-Sweep GC
    • -XX:+UseParNewGC -- ParNew + Serial MSC
    • -XX:+UseParallelOldGC -- Parallel Scavenge + Parallel Mark Sweep

    收集参数设置

    • -XX:ParallelGCThreads=n:设置并行收集器操作使用的CPU数量
    • -XX:MaxGCPauseMillis=n:设置并行收集器的最大暂停时间,单位为毫秒
    • -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比
    • -XX:+CMSIncrementalMode:设置增量模式,适合单CPU模式。需要使用-XX:+UseConcMarkSweepGC策略

    测试代码:

    package cn.liang.jvm;
    public class gctest2 {
    	public static void main(String[] args) {
    		String string = "liang";
    		while (true) {
    			string += string + string;
    			string.intern();	
    		}
    	}
    }
    

    默认的GC策略:Parallel Scavenge + Parallel MSC

    -Xmx10m -Xms10m -XX:+PrintGCDetails
    
    输出结果:
    [Full GC (Allocation Failure) 
    [PSYoungGen: 0K->0K(1536K)] 
    [ParOldGen: 4082K->4070K(7168K)] 4082K->4070K(8704K), 
    [Metaspace: 2649K->2649K(1056768K)], 0.0047164 secs] 
    [Times: user=0.00 sys=0.00, real=0.01 secs]
    

    使用串行GC策略:Serial Copying + Serial MSC

    -Xmx10m -Xms10m -XX:+UseSerialGC -XX:+PrintGCDetails
    
    输出结果:
    [GC (Allocation Failure) 
    [DefNew: 2581K->2581K(3072K), 0.0000758 secs]
    [Tenured: 5989K->4084K(6848K), 0.0034008 secs] 8570K->4084K(9920K), 
    [Metaspace: 2649K->2649K(1056768K)], 0.0035313 secs] 
    [Times: user=0.00 sys=0.00, real=0.01 secs]
    

    使用并行GC策略:Parallel Scavenge + Parallel Mark Sweep

    -Xmx10m -Xms10m -XX:+UseParallelGC -XX:+PrintGCDetails
    
    输出结果:
    [Full GC (Allocation Failure) 
    [PSYoungGen: 224K->0K(2560K)] 
    [ParOldGen: 5347K->2816K(7168K)] 5571K->2816K(9728K), 
    [Metaspace: 2648K->2648K(1056768K)], 0.0039458 secs] 
    [Times: user=0.01 sys=0.00, real=0.01 secs]
    

    使用CMS回收:ParNew + Concurrent Mark-Sweep GC

    • 这对整个程序的暂停时间会非常短暂,适合于响应速度快的程序
    -Xmx10m -Xms10m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails
    
    输出结果:
    [GC (Allocation Failure) 
    [ParNew: 2584K->2584K(3072K), 0.0000325 secs]
    [CMS (concurrent mode failure): 4941K->4087K(6848K), 0.0030993 secs] 7526K->4087K(9920K), 
    [Metaspace: 2649K->2649K(1056768K)], 0.0032009 secs] 
    [Times: user=0.00 sys=0.00, real=0.00 secs]
    

    总结:

    • 如果程序没有对运行速度要求的话,建议使用默认的GC策略
    • 所有的GC策略都有一个问题:都需要扫描全部子内存
  • 相关阅读:
    js中return的作用及用法
    js数组、字符串常用方法
    关于Ajax知识点小节
    关于跨域,同源策略小节
    Javascript模块化编程(三):require.js的用法【转】
    Javascript模块化编程(二):AMD规范【转】
    Javascript模块化编程(一):模块的写法【转】
    AJAX——核心XMLHttpRequest对象
    clientX,screenX,pageX,offsetX的异同 【转载】
    原生js获取鼠标坐标方法全面讲解:clientX/Y,pageX/Y,offsetX/Y,layerX/Y,screenX/Y【转】
  • 原文地址:https://www.cnblogs.com/liangjingfu/p/10007884.html
Copyright © 2020-2023  润新知