乐趣区

关于java:JVM系列6GC与调优1

JVM 系列笔记目录

  • 虚拟机的根底概念
  • class 文件构造
  • class 文件加载过程
  • jvm 内存模型
  • JVM 罕用指令
  • GC 与调优

GC 基础知识

  • 什么是垃圾

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

  • 如何找到垃圾

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

什么是根?留神联合上一篇博客 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)

      毛病:地位不间断,产生碎片,效率偏低(须要进行两遍扫描)

      实用状况:算法绝对简略,实用于存活对象比拟多的状况

    2. 拷贝算法 (copying)

      阐明:没有碎片,节约空间,复制挪动对象,须要调整对象援用

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

    3. 标记压缩(mark compact)

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

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

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

    分代模型中,分新生代和老年代,比例是 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 连问 - 对象如何调配,简略提过这一点。

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

      > 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。

      • Serial

        年老代 串行回收

      • SerialOld

        老年代 串行回收

      • PS(ParallelScavenge)

        年老代 并行回收

      • PO(ParallelOld)

        老年代 并行回收

      • 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 能够反对)

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

    退出移动版