GC调优

如何确定垃圾对象
    引用计数
        无法排除对象的相互引用
    枚举根节点,做可达性分析——JAVA目前使用的垃圾回收思想

    根节点:类加载器、Thread 、虚拟机栈的本地变量表、static成员、常量引用、本地方法栈的变量等等

垃圾回收的算法
    标记清除:效率不高,标记和清除两个过程的效率都不高,产生碎片,碎片太多会导致提前GC
    复制:     实现简单,运行高效,但是空间利用率较低---YOUNG区所使用的
    标记整理:没有了内存碎片,但是整理内存比较耗时

分带垃圾回收---目前JVM所使用的
    Young区用复制算法
    Old区用标记清除或者标记整理

对象分配
    对象优先在Eden区分配
    大对象直接进入老年代:-XX:PretenureSizeThreshold(超过该参数指定的大小,即为大对象)
    长期存活的对象将进入老年代:对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置。
        另外两种方法:
            -XX:TargetSurvivorRatio:设置ygc之后存活对象比例,比方说80%,之后计算这80%对象的平均年龄,之后平均年龄和PretenureSizeThreshold值取一个最小值,如果有对象达到这个最小值,则晋升到Old区
            -XX:PrintTenuringDistribution:发生YGC之后,打印下存活对象的年龄分布情况

    参考:https://www.jianshu.com/p/fa3569127416

垃圾收集器
    垃圾器种类:
    串行收集器Serial:    Serial 、 Serial Old
    并行收集器Parallel:    Parallel Scavenge 、 Parallel Old ---吞吐量优先
    并发收集器Concurrent:CMS 、 G1 ---停顿时间优先

    参考:https://blog.csdn.net/tjiyu/article/details/53983650

    停顿时间:
        垃圾收集器做垃圾回收时中断应用执行时间
        -XX:MaxGCPauseMillis        最大停顿时间

    吞吐量:    
        花在垃圾收集时间和花在应用时间的占比
        -XX:GCTimeRatio=<n>,垃圾收集时间占比:1/(1+n)
            eg:n=19  则垃圾收集时间占用5%

    设置方法:
        串行收集器:-XX:+UseSerialGC -XX:+UseSerialOldGC            设置第一个参数后,默认启用第二个参数
        并行收集器:-XX:+UseParallelGC , -XX:+UseParallelOldGC    设置第一个参数后,默认启用第二个参数
            Server模式下默认收集器
        CMS:-XX:+UseConcMarkSweepGC -XX:UseParNewGC                设置第一个参数后,默认启用第二个参数
        G1:-XX:+UseG1GC

        参考:http://www.importnew.com/13827.html
        http://ifeve.com/useful-jvm-flags-part-7-cms-collector/

    验证启用垃圾收集器的类型的方法
        jinfo -flag UseParallelGC 84231
        jinfo -flag UseParallelOldGC 84231
        jinfo -flag UseConcMarkSweepGc 84231
        jinfo -flag UseG1GC 84231

    并行和并发收集器的适用场景
        并行:适合科学计算,后台处理等弱交互场景
        并发:对响应时间有要求的场景,比如WEB

    如何选择垃圾收集器    选择垃圾收集器的指导规则
        优先调整堆的大小让服务器自己选择
        如果内存小于100M,使用串行收集器
        如果是单核,并且没有停顿时间的要求,串行或者JVM自己选
        如果允许停顿时间超过1S,选择并行或者JVM自己选
        如果响应时间最重要,并且不能超过1S,使用并发收集器        


    UseParallel Collector
        -XX:+UseParallelGC     手动开启,Server默认开启
        -XX:ParallelGCThreads=<N>    多少个GC线程
            CPU>8    开启N=5/8
            CPU=8    开启N=CPU
    UseParallel Collector Ergonomics    并行收集器有自适应的特性
        -XX:MaxGCPauseMillis=<N>        最大停顿时间
        -XX:GCTimeRatio=<N>                吞吐量
        -Xmx<N>                            最大堆的大小

        动态内存调整        自适应的内存调整参数
            -XX:YoungGenerationSizeIncrement=<Y>    默认值20% Young区自增参数
            -XX:TenuredGenerationSizeIncrement=<T>    默认值20% Old区自增参数
            -XX:AdaptiveSizeDecrementScaleFactor=<D>默认值4% 自减参数

    CMS Collector
        并发收集
        低停顿、低延迟
        老年代收集器

    CMS垃圾收集过程
        CMS initial mark:初始标记    STW(stopTheWorld)
        CMS concurrent mark:并发标记
        CMS-concurrent-preclean:并发预清理
        CMS remark:重新标记    STW
        CMS concurrent sweep:并发清除
        CMS-concurrent-reset:并发重置

    CMS缺点
        CPU敏感
        浮动垃圾
        空间碎片

    CMS相关参数
        -XX:ConcGCThreads:    并发的GC线程数    与应用程序并发执行时,GC的并发线程数,并非STW时的线程数
        -XX:+UseCMSCompactAtFullCollection:    FullGC之后做压缩        主要作用是为了减少内存碎片
        -XX:CMSFullGCsBeforeCompaction:    多少次FullGC之后压缩一次        压缩是比较耗时的,所以并不是每次FullGC后都会进行压缩
        -XX:CMSInitiatingOccupancyFraction:    触发FullGC    Old区占有多少存活对象时触发FullGC  默认是92%
        -XX:+UseCMSInitiatingOccupancyOnly:    是否动态可调    
        -XX:+CMSScavengeBeforeRemark:    FullGC之前先做YGC    一般调优时,会打开此参数
        -XX:+CMSClassUnloadingEnabled:    启用回收Perm区    JDK7之前有Perm区

    iCMS    Incremental CMS     增量的CMS    JDK8已废弃
        适用于单核 双核


    G1 Collector
        大内存 优先的延迟        6G+ <0.5s
    G1的几个概念
        Region
        SATB:Snapshot-At-The-Beginning,它是通过Root Tracing得到的,GC开始时存活对象的快照        后面GC回收以此为基础
        RSet:记录了其他Region中的对象引用本Region中的对象的关系,属于points-into结构(谁引用了我的对象)

    YoungGC
        新对象进入Eden区
        发生YGC之后,存活对象拷贝到Survivor区
        存活时间到达年龄阈值时,对象晋升到Old区

    MixedGC        无fullGC,新增MixedGC
        MixedGC不是FullGC,动作是回收所以Young和部分Old
        global concurrent marking        全局并发标记
    
    global concurrent marking
        Initial marking phase:            标记GC Root     STW
        Root region scanning phase:        标记存活region
        Concurrent marking phase:        标记存活的对象
        Remark phase:                    重新标记        STW
        Cleanup phase:                    部分STW

    MixedGC时机
        InitiatingHeapOccupancyPercent:
            堆占有率达到这个数值则触发global concurrent marking,默认45%
        G1HeapWastePercent:
            在global concurrent marking结束之后,可以知道区有多少空间要被回收,在每次YGC之后和再次发生MixedGC之前,会检查垃圾占比是否达到此参数,只要达到了,下次才会发生MixedGC.
        G1MixedGCLiveThresholdPercent:
            Old区的region被回收时候存活对象占比
        G1MixedGCCountTarget:
            一次global concurrent marking之后,最多执行MixedGC的次数
        G1OldSetRegionThresholdPercent:
            一次Mixed GC中被选入CSet的最多Old区的region数量        一次MixedGC最多回收多少Old区的region

    常用参数
        -XX:+UseG1GC        开启G1
        -XX:G1HeapRegionSize=<n>    region的大小 1-32M 最多不能超过2048个        设置每个Region大小,范围1MB到32MB;目标是在最小Java堆时可以拥有约2048个Region;
        -XX:MaxGCPauseMillis        为G1设置暂停时间目标,默认值为200毫秒
        -XX:G1NewSizePercent    
        -XX:G1MaxNewSizePercent
        -XX:G1ReservePercent=10        保留防止to space溢出 默认10%
        -XX:ParallelGCThreads=n        STW线程数    需要停止应用程序
        -XX:ConcGCThreads=n            并发线程数=1/4*并行

    最佳实现
        年轻代大小:避免使用-Xmn -XX:NewRatio等显式设置Young区大小,会覆盖暂停时间目标
        暂停时间目标:暂停时间不要太严苛,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响吞吐量

        另外的知识点:
            https://blog.csdn.net/lovewebeye/article/details/80911838
            -XX:newSize:表示新生代初始内存的大小,应该小于-Xms的值;
            -XX:MaxnewSize:表示新生代可被分配的内存的最大上限;当然这个值应该小于-Xmx的值;
            -Xmn:至于这个参数则是对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置,也就是说如果通过-Xmn来配置新生代的内存大小,那么-XX:newSize = -XX:MaxnewSize = -Xmn,虽然会很方便,但需要注意的是这个参数是在JDK1.4版本以后才使用的。


    是否需要切换到G1
        50%以上的堆被存活的对象占用    查看命令是jmap -heap 86624
        对象分配和晋升的速度变化非常大
        垃圾回收时间特别长,超过了1秒


可视化GC日志分析工具
    评价一个垃圾收集器是否好坏的指标:吞吐量 响应时间  同样进行调优 也就是要调这两个值
    我们主要通过GC日志得到这两个值

    打印日志相关参数
        -XX:+PrintGCDetails                            打印GC详细信息
        -XX:+PrintGCTimeStamps                        输出GC的时间戳(以基准时间的形式)
        -XX:+PrintGCDateStamps                        输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800-Xloggc:$CATALINA_HOME/logs/gc.log
        -XX:+PrintHeapAtGC                            发生GC时,打印整个堆的使用情况
        -XX:+PrintTenuringDistribution                发生YGC之后,打印下存活对象的年龄分布情况

    ParallelGC日志格式


GC调优步骤
    打印GC日志
    根据日志得到关键性能指标
    分析GC原因,调优JVM参数

初始参数---获取gc日志
    -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/gclog/tomcat8180_DumpOnOutOfMemoryError.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/data/logs/gclog/tomcat8180-gc.log -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution


    -XX:+DisableExplicitGC                         禁用掉明确的GC    禁用代码中的手动GC调用
    -XX:+HeapDumpOnOutOfMemoryError             当发生内存溢出时,打印内存映像
    -XX:HeapDumpPath=$CATALINA_HOME/logs/ 
    -XX:+PrintGCDetails                         
    -XX:+PrintGCTimeStamps 
    -XX:+PrintGCDateStamps 
    -Xloggc:$CATALINA_HOME/logs/gc.log

    常用参数
        -XX:+UseCompressedOops
        -XX:+UseCompressedClassPointers

Parallel GC调优原则
    除非确定,否则不要设置最大堆内存
    优先设置吞吐量目标
    如果吞吐量不达标,调大最大内存,不能让OS使用Swap,如果仍然达不到,减低目标
    吞吐量能达到,GC时间太长,设置停顿时间目标


ParallelGC调优
    设置Metaspace大小
        -XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M
    添加吞吐量和停顿时间参数
        -XX:GCTimeRatio=99 -XX:MaxGCPauseMillis=100
    修改动态扩容增量
        -XX:YoungGenerationSizeIncrement=30    默认值20%,现修改为30%


G1 GC最佳实践
    年轻代大小:避免使用-Xmn / -XX:NewRatio等显式设置Young区大小,会覆盖暂停时间目标。
    暂停时间目标:暂停时间不要太苛刻,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响到吞吐量。

关于MixGC调优
    -XX:InitiatingHeapOccupancyPercent
    -XX:G1MixedGCLiveThresholdPercent
    -XX:G1HeapWastePercent
    -XX:G1MixedGCCountTarget
    -XX:G1OldCSetRegionThresholdPercent

G1调优相关参数
    -XX:+UseG1GC -Xms128M -Xmx128M -XX:MetaspaceSize=64M -XX:MaxGCPauseMillis=100 -XX:+UseStringDeduplication -XX:StringDeduplicationAgeThreshold=3

并行垃圾收集器是吞吐量优先
并发垃圾收集器是停顿时间优先

参考:

  G1垃圾回收器调优

  G1最佳实践

原文地址:https://www.cnblogs.com/jxdong116/p/9713240.html