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

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