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 默认的收集器

网友评论