zoukankan      html  css  js  c++  java
  • JVM系列【6】GC与调优1

    JVM系列笔记目录

    • 虚拟机的基础概念
    • class文件结构
    • class文件加载过程
    • jvm内存模型
    • JVM常用指令
    • GC与调优

    GC基础知识

    • 什么是垃圾

    ​ 没有任何引用指向的一个对象或多个对象(循环引用)

    file

    • 如何找到垃圾

      • 引用计数(ReferenceCount),缺点:无法解决循环引用
      • 根可达算法(RootSearching),从根开始查找,找到对象是有用的,找不到的对象为垃圾。

    file

    什么是根? 注意结合上一篇博客 JVM系列【5】JVM常用指令-运行时数据区进行理解。

    1. 线程栈变量 JVM Stack、native method stack
    2. 静态变量 static refercences in method area、Clazz
    3. 常量池 runtime cosntant pool
    4. JNI指针 c/c++ 指针
    • 常见的垃圾回收算法

      1. 标记清除(mark sweep)

      缺点:位置不连续,产生碎片,效率偏低(需要进行两遍扫描)

      适用情况:算法相对简单,适用于存活对象比较多的情况
      file

      1. 拷贝算法 (copying)

        说明:没有碎片,浪费空间,复制移动对象,需要调整对象引用

        适用情况:适用于存活对象较少的情况 只扫描一次

        file

      2. 标记压缩(mark compact)

        说明:没有碎片,效率偏低(两遍扫描,指针需要调整)

      file

    • JVM堆内存分代模型(用于分代垃圾回收算法)

      堆内存分代模型是部分垃圾回收器使用的模型,除Epsilon ZGC Shenandoah 之外的GC都使用逻辑分代模型,但是G1 是逻辑分代 物理不分代,除此之外都是逻辑分代 而且物理分代。

      file

      分代模型中,分新生代和老年代,比例是1:2

      1. 新生代 = Eden区+ 2个survivor区

        YGC回收后,大多数的对象会被回收,活着的进入s0;

        再次YGC,活着的对象eden+s0 进入s1;

        再次YGC,活着的对象eden+s1 进入s0;

        年龄足够进入老年代,一般垃圾回收器是15,CMS是6;为什么一般垃圾回收器分代年龄是15?参考下 JVM系列【4】内存模型-对象头的内容有哪些,对象头中4位标识GC年龄,所以最大的年龄是2^4 -1 = 15

        s 区装不下,直接进入老年代。

      2. 老年代: 存放一些"顽固对象",老年代满了或是分配不下了会触发FCG。

      3. 永久代(Permanent Generation,JDK1.7以前)/元数据区(MetaSpace,JDK1.8以后):存放的是Class文件结构,永久代必须指定大小限制 ,元数据可以设置也可以不设置,无上限(受限于物理内存),字符串常量在1.7以前存放在永久代,1.8以后存放在堆中。

    • 垃圾回收类型和对象分配过程

      1. 垃圾回收类型

        上一个点解释了堆内存分代模型,这里统一下概念:MinorGC=YGC指的是新生代即Y区的垃圾回收,MajorGC=FGC指的是老年代分配不下或是满了发生的GC,包括新生代和老年代。

      2. 对象如何分配

        在之前的博客中 JVM系列【4】内存模型-new Object()面试6连问-对象如何分配,简单提过这一点。

    file

    ​ 对照流程图,分配过程:

    	> 1. new对象后优先在栈上分配,栈上分配的对象`pop`后就消失;
    	> 2. 是否是大对象(Y区分配不下的对象)?是就分配到O区,O区发生FGC后回收
    	> 3. 不是大对象,优先分配TLAB(Thread Local Allocation Buffer线程本地分配缓存)上,分配不下就分配到Eden区 。
    
    1. 了解栈上分配、TLAB、分配担保机制和升代

      1. 哪些对象栈上分配?

        线程私有对象 、无逃逸对象即离开代码块就没有引用的对象、支持标量替换的对象,如类中变量可以用基本变量替换。

      2. 线程本地分配Thread Local Allocation Buffer
        独占eden空间,默认1%;多线程时候不用竞争eden就可以申请空间,提高效率;可分配小对象

      3. 分配担保机制

        在新生代无法分配内存的时候,把新生代的对象转移到老生代,然后把新对象放入腾空的新生代。参考

      4. 对象何时进入老年代?

        超过MaxTenuringThreshold指定的次数;

        根据动态年龄计算进入老年代,Survivor空间中年龄从小到大的对象进行累加,当加入某个年龄段后,累加和超过survivor区域*TargetSurvivorRatio(默认50%)的时候,就从这个年龄段往上的年龄的对象进行晋升到老年代。参考

    • 常见的垃圾回收器

      常见的垃圾回收器有Serial/SerialOld、ParallelScavenge/ParallelOld、ParNew/CMS、G1、ZGC、Shenandoah、Epsilon。Serial/SerialOld、ParallelScavenge/ParallelOld、ParNew/CMS是分代的垃圾回收器,G1是逻辑上分代物理上不分代,ZGC和Shenandoah是不分代,Epsilon是JDK调试用的垃圾回收器。

      历史:JDK诞生,Serial追随,为了提供效率诞生PS,为配合CMS,诞生PN,CMS是1.4后期引入的,CMS是里程碑式的GC,但是CMS毛病比较多,因此目前没有任何一个JDK版本默认CMS。

    file

    • Serial

      年轻代 串行回收

      file

    • SerialOld

      老年代 串行回收

      file

    • PS(ParallelScavenge)

      年轻代 并行回收

      file

    • PO(ParallelOld)

      老年代 并行回收

      file

    • PN(ParNew)

      年轻代 增强版PS配合CMS的并行回收。PN 和 PS区别?PN 响应时间优先;PS吞吐量优先

    • CMS(ConcurrentMarkSweep)

      老年代并发的,垃圾回收和应用程序同时运行,降低STW的时间(200ms);

      CMS问题比较多,所以现在没有一个版本默认是CMS,只能手工指定;

      CMS既然是MarkSweep,就一定会有碎片化的问题,碎片到达一定程度,CMS的老年代分配对象分配不下的时候,使用SerialOld 进行老年代回收,STW无法忍受;

      • 如何解决碎片化:设定-XX:+UseCMSCompactAtFullCollection 默认开启;设定-XX:CMSFullGCsBeforeCompaction,默认为0 指经过多少次FGC才进行压缩。
      • 浮动垃圾问题解决?降低触发CMS的阈值,保持老年代有足够的空间;参数-XX:CMSInitiatingOccupancyFraction 指定使用CMS时老年代使用了指定阈值的内存后触发FGC,建议68-92%

      使用的算法:三色标记+Increamental Update

    • G1

      STW可以达到10ms

      算法:三色标记+SATB

    • ZGC

      STW号称可以达到1ms

      算法:颜色指针ColoredPointers + LoadBarrier

    • Shenandaoh

      算法:ColoredPointers + WriteBarrier

    • 垃圾回收器和内存大小的关系

      Serial 几十兆

      PS 上百兆-几个G

      CMS 20G左右

      G1 上百G

      ZGC 4T-16T(JDK13可以支持)

    知识分享,转载请注明出处。学无先后,达者为先!

  • 相关阅读:
    .NET Page对象各事件执行顺序
    允许webservice远程在ie里面调用配置方法
    sea.js模块化编程
    atom配置web开发环境
    CSS代码规范
    HTML DOM总结
    10分钟写一个markdown编辑器
    sea.js详解
    圣杯布局 双飞翼布局
    Spring学习(1)
  • 原文地址:https://www.cnblogs.com/kongbubihai/p/13821222.html
Copyright © 2011-2022 走看看