美文网首页
JVM堆的分配和回收

JVM堆的分配和回收

作者: Tinyspot | 来源:发表于2022-06-30 07:50 被阅读0次

1. 内存分配

  • 现代收集器基本都采用分代收集算法

1.1 概述

  • 垃圾收集
  • 垃圾回收
  • 垃圾收集器
  • GC 算法是内存回收的方法论,垃圾收集器就是算法落地实现

1.2 堆

  • 堆分成两大块:新生代和老年代。对象产生之初在新生代,步入暮年进入老年代,但是老年代也接纳再新生代无法容纳的超大对象。
  • 新生代 = 1 个 Eden 区 + 2 个 Survivor 区(From Survivor, ToSurvivor)
  • 绝大部分对象在 Eden 区生成,当 Eden 区装填满的时候,会触发 Young Garbage Collection, 即 YGC。
  • 垃圾回收的时候,在 Eden 区实现清除策略,没有被引用的对象则直接回收,依然存活的对象会被移送到 Survivor 区。Survivor 分为 S0 和 S1 两块内存空间,每次 YGC 的时候,它们将存活的对象复制到未使用的那块空间,然后将当前正在使用的空间完全清楚,交换两块空间的使用状态。如果 YGC 要移送的对象大于 Survivor 区容量的上限,则直接移交给老年代

1.3 STW

  • Stop-the-world 暂停整个应用

2. 垃圾收集

  • 对象存活分析

2.1 最古老的方法:引用计数算法

  • 给每一个对象添加一个引用计数器;每当有一个地方引用它时,计数器+1,引用失效则 -1;当计数器不为 0 时,判断该对象存活,否则判断为死亡
  • 缺陷:无法解决对象间相互循环引用的问题

2.2 可达性分析算法 (JVM采用的算法)

  • 将一系列的 GC Roots 对象作为起点,从这些起点开始向下搜索
  • 当一个对象到 GC Roots 没有任何引用链相连时,则判断该对象不可达
  • GC Roots 包括:
    • 虚拟机栈(栈帧中的局部变量表)中引用的对象
    • 方法区中类静态属性引用的对象(类变量也叫静态变量或静态属性
    • 方法区中常量引用的对象
    • 本地方法栈中 JNI 引用的对象

2.3 对象的引用决定对象的生死

  • 强引用
    • new 对象
  • 软引用 - SoftReference
    • 用来描述一些还有用但并非必需的对象
  • 弱引用 - WeakReference
    • 被弱引用关联的对象只能生存到下一次垃圾收集发生之前
  • 虚引用
    • PhantomReference

3. 垃圾回收算法(GC算法)

3.1 标记-清除算法

  • 两个阶段:标记阶段,清除阶段
  • 缺点:存在大量内存碎片

3.2 标记-复制算法

  • 将内存划分为大小相等的两块,每次只使用其中一块
  • 当这一块内存用完后,将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理
  • 缺点
    • 浪费内存空间
    • 对象存活率较高时,需要较多复制操作

3.3 标记-整理算法

  • 标记-复制 算法类似,但是标记-整理算法不是把存活对象复制到另一块内存,而是把存活对象往内存一端移动,然后直接回收边界以外的内存,因此不会产生内存碎片
  • 缺点:
    • 效率不高,因为不仅要标记存活的对象,还需整理存活对象的地址
    • 没有 标记-复制算法 高效

4. 垃圾收集器

  • 类型:串行,并行,并发和 G1
  • 新生代垃圾收集器
    • Serial 收集器、ParNew 收集器、Parallel Scavenge 收集器
  • 老年代垃圾收集器
    • Serial Old 收集器、Parallel Old 收集器、CMS 收集器
  • 不存在物理隔离分代(回收整个Java堆:新生代和老年代)
    • G1

4.1 Serial 串行收集器

  • 新生代单线程收集器
  • 只用一个线程进行垃圾回收,会暂停所有的用户线程
  • 年轻代采用复制算法,老年代采用标记-整理算法

4.2 Serial Old

  • Serial 的老年代版本,也是单线程收集器
  • 基于“标记-整理”算法
  • Java8 已废弃

4.3 ParNew

  • 是 Serial 收集器的多线程版本

4.4 Parallel Scavenge

  • 并行回收收集器
  • 多个垃圾收集线程并行工作,此时用户线程是暂停的

4.5 Parallel Old

  • Parallel Scavenge 的老年代版本
  • 基于“标记-整理”算法

4.6 CMS

  • Concurrent Mark Sweep 并发收集、低停顿(最短回收停顿时间)
  • 基于“标记-清除”算法
  • 用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程
  • 四个步骤:
    • 初始标记 - 标记 GCRoots 能关联的对象
    • 并发标记
    • 重新标记 - 修正
    • 并发清除

4.7 G1

  • 把内存“化整为零”,即将堆内存分割成不同的区域然后并发的对其进行垃圾回收
  • 步骤:
    • 初始标记
    • 并发标记
    • 最终标记
    • 筛选回收

5. 查看垃圾收集器

命令行 java -XX:+PrintCommandLineFlags -version
Java8 默认是并行回收收集器 -XX:+UseParallelGC

  • 表示激活,开启
-XX:InitialHeapSize=533666368 -XX:MaxHeapSize=8538661888 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
 -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.8.0_77"
Java(TM) SE Runtime Environment (build 1.8.0_77-b03)
Java HotSpot(TM) 64-Bit Server VM (build 25.77-b03, mixed mode)

5.1 Java 默认的收集器

image.png

相关文章

网友评论

      本文标题:JVM堆的分配和回收

      本文链接:https://www.haomeiwen.com/subject/swrtxltx.html