GC 及 JVM Tuning

GC的基础知识

#### 1.什么是垃圾

illustration

> C语言申请内存:malloc free > > C++: new delete > > c/C++ 手动回收内存-比较精确-开发效率低 > > Java: new ? > > 自动内存回收-编程上简单-系统不容易出错-手动释放内存-容易出两种类型的问题: > > 1. 忘记回收 > 2. 多次回收

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

illustration

#### 2.如何定位垃圾

illustration illustration

  • 引用计数(ReferenceCount)
  • 不能解决循环引用-可能都是1

    illustration

  • 根可达算法(RootSearching)
  • illustration

    #### 3.常见的垃圾回收算法

    illustration

  • 标记清除(mark sweep) - 没用的标记出来-直接清掉-其他不动
  • 不适合伊甸区 位置不连续-容易产生碎片-效率偏低(两遍扫描:1.找出有用的 2。找出没用的) 算法相对简单-存活对象比较多的情况下效率较高

    illustration illustration

  • 拷贝算法 (copying) - 有用的拷贝过来
  • 适合伊甸区 浪费空间 移动复制对象-需要调整对象引用 适用于存活对象较少的情况-只扫描一次-效率提高

    illustration !image-20200514202929940

  • 标记压缩(mark compact) - 有用的聚到一起-没用的清掉-空间是连续的-慢
  • 没有碎片-方便对象分配 不会产生内存减半 需要移动对象-效率偏低(两遍扫描-指针需要调整)

    illustration illustration

    #### 4.JVM内存分代模型(用于分代垃圾回收算法)

  • 部分垃圾回收器使用的模型
  • illustration 新生代大量复制-少量存活-采用‘复制’算法 老年代存活率高-回收较少-采用‘标记清除’或‘标记压缩’

    > 除Epsilon ZGC Shenandoah之外的GC都是使用逻辑分代模型 > > G1是逻辑分代-物理不分代 > > 除此之外不仅逻辑分代-而且物理分代

    逻辑分代: illustration新生代大量复制-少量存活-采用‘复制’算法 老年代存活率高-回收较少-采用‘标记清除’或‘标记压缩’

  • 新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace
  • 1. 永久代 元数据 - Class 2. 永久代必须指定大小限制 -元数据可以设置-也可以不设置-无上限(受限于物理内存) 3. 字符串常量 1.7 - 永久代-1.8 - 堆 4. MethodArea逻辑概念 - 永久代、元数据

  • 新生代 = Eden + 2个suvivor区
  • 默认8:1:1 1. YGC回收之后-大多数的对象会被回收-活着的进入s0 2. 再次YGC-活着的对象eden + s0 -> s1 3. 再次YGC-eden + s1 -> s0 4. 年龄足够 -> 老年代 (15 CMS 6) 5. s区装不下 -> 老年代

  • 老年代
  • 1. 顽固分子 2. 老年代满了FGC Full GC

  • GC Tuning (Generation)
  • illustration 1. 尽量减少FGC 2. MinorGC = YGC:年轻代空间耗尽时触发 3. MajorGC = FullGC:在老年代无法继续分配空间时触发-新生代 4. -Xms 最小内存 5. -Xmx 最大内存

  • 对象分配过程图
  • 1. 首先尝试栈上分配-分配不下-进入伊甸区 2. 1次垃圾回收之后-进入survivor幸存区-来回复制 3. 多次垃圾回收之后-进入old去illustrationillustration

    illustration

  • 什么情况下-栈上分配(无需人工调整)
  • 1. 线程私有的小对象 2. 无逃逸:只在某一段代码使用-没有被外部引用所引用illustration 3. 支持标量替换:用普通属性代替整个对象
  • 什么情况下-线程本地分配TLAB
  • 1. 每个线程在eden取1%的空间-分配对象时-优先往这块空间分配

    ###### 何时进入老年代

    illustration

  • Mark word对象头中-GC的Age是4位-最大15-不能调大
  • Eden + S1 进入S2-超过S2的50%-年龄最大的放进Oldillustration
  • illustration

  • 动态年龄:(不重要)
  • https://www.jianshu.com/p/989d3b06a49d
  • 分配担保:(不重要)
  • YGC期间 survivor区空间不够了 空间担保直接进入老年代 参考:https://cloud.tencent.com/developer/article/1082730

    #### 5.常见的垃圾回收器

    illustration

    JDK诞生 Serial(单线程)第一个诞生 提高效率-诞生了PS-为了配合CMS-诞生了PN-CMS是1.4版本后期引入-CMS是里程碑式的GC-它开启了并发回收的过程-但是CMS毛病较多-因此目前任何一个JDK版本默认是CMS 并发垃圾回收是因为无法忍受STW

    常见组合:这些逻辑上-物理上都分代 illustration

    G1:只在逻辑上分代

  • Serial(单线程) 年轻