东东
发布于 2022-11-11 / 101 阅读 / 0 评论 / 0 点赞

JVM垃圾回收

  • Java自动内存管理的核心功能就是 内存中的对象的分配和回收
  • 垃圾收集器管理的主要区域就是 ,因此也叫 GC堆
  • 垃圾收集器目前基本采用的是分代收集算法
  • JDK1.8之后,永久代被元空间代替,使用的直接内存,堆中就剩下新生代老年代
  • 新生代分为Eden、两个S区

image-1668146988206

内存分配和回收原则

对象优先在Eden区进行分配

  1. 大多数情况下,对象在新生代的Eden区进行分配
  2. 如果没有足够的空间,则触发一次MinorGC,存活的对象进行from区,对象年龄加1,此时如果大对象无法放入from,则直接进入老年代
  3. 当eden区满了后,再次触发MinroGC,Eden区存活对象进入from区,并且from区采用标记复制法移动到to区,对象年龄加1,然后to区和from区名字交换。(即哪个区空着哪个区叫to区)

大对象直接进入老年代

  • 大对象就是需要连续内存空间的对象,比如字符串、数组;
  • 直接进入老年代也是避免在年轻代是放不下还要复制进老年代

长期存活的对象将进入老年代

  1. 虚拟机为每个对象一个年龄计数器
  2. 对象在Eden区分配出生,经过一次年轻代GC后如果还存活,就移动到from区,年龄加1
  3. 对象在存活区每经过一次年轻代GC,年龄就加1,当年龄增加到一定程度(默认15岁),就会放入老年代中

总结

  1. 新生代GC:只对新声嗲进行垃圾回收
  2. fullGC:手机整个Java堆

死亡对象的判断

  1. 已经死亡的对象才能被回收

引用技术法

  1. 给对象添加一个引用计数器
  2. 有一个引用就加1
  3. 引用失效就减1
  4. 计数器为0的可以认为是死亡对象

循环引用问题

  1. 两个对象间相互引用,会导致两个对象的计数器都不是0
  2. 两个对象都没有其他引用,实际为死亡对象。

此种情况无法通过垃圾回收器进行回收

可达性分析算法

  1. 以“GC-Roots”的对象为起点
  2. 从这些节点向下搜索,节点走过的路径叫引用链
  3. 当一个对象到GC Roots没有任何引用链时,对象不可达

哪些对象可以作为GC Roots

  • 虚拟机栈中引用的对象
  • 本地方法栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 所有被同步锁持有的对象

对象可以回收,代表对象一定会被回收吗?

  1. 不可达对象也需要进行两次标记
  2. 不可达时进行第一次标记,并筛选是否有必要执行finalize方法
  3. 需要执行的进行第二次标记,进而被回收

引用类型的分类

不管是哪种判断对象死亡的方法,都需要判断对象是否存在引用。
Java中分为四种引用,依次是

  1. 强引用
  2. 软引用
  3. 弱引用
  4. 虚引用

强引用

  1. 最普遍的引用
  2. 强引用绝对不会被回收
  3. 当内存不足时,抛出OOM错误,也不会进行回收

软引用

  1. 软引用可有可无
  2. 当内存足够时,不会回收
  3. 内存不够时,就会回收
  4. 软引用可以实现内存敏感的高速缓存

弱引用

  1. 弱引用可有可无
  2. 无论内存是否足够,只要发生GC,就会回收

虚引用

  1. 任何时候都可能被垃圾回收

总结

  1. 实际使用过程中,很少会用到弱引用和虚引用
  2. 软引用可以加速JVM堆垃圾内存的回收速度,防止OOM

如何判断一个常量时废弃的

如果字符串常量池中的一个字符串没有任何对象引用,就是废弃的字符常量

垃圾回收算法

标记-清除

  1. 第一轮统一进行标记,标记出所有不需要进行回收的对象
  2. 标记完成后,统一回收掉没有标记的对象

问题

  1. 效率低
  2. 产生空间碎片

标记-复制

  1. 将内存等分位两块,每次使用其中一块
  2. 一块内存使用完之后,将存活对象复制到另一块
  3. 复制完成后,将当前块的清理掉

问题

  1. 可用内存减半

标记-整理

  1. 首先进行存活对象的标记
  2. 将所有的存活对象向同一段进行移动
  3. 移动完成后,清理掉边界之外的所有内存

分代收集

  1. 根据不同代的特点进行不同的收集算法
  2. 新生代对象的出生死亡频繁,可以选择标记复制
  3. 老年代对象存活几率高,可以采用标记整理

垃圾收集器

Serial收集器(串行收集器)

  1. 单线程
  2. 垃圾回收的同时必须暂停其他线程,直到回收结束
  3. 新声代标记复制,老年代标记整理
  4. 特点:简单高效

ParNew收集器

  1. 串行收集器的多线程版本
  2. 多线程并发,应用暂停

Parallel Scavenge收集器

  1. 可并发收集器几乎一样
  2. 并行收集器更关注吞吐量,提供参数可以调整最大吞吐量和用户线程的停顿时间
  3. JDK1.8的默认收集器

CMS收集器

  1. CMS收集器时一种以获取最短回收停顿时间为目标的收集器
  2. 并发收集器,可以实现垃圾回收和用户线程基本同时工作
  3. 采用标记清除算法

执行过程

  1. 初始标记:暂停其他所有线程,记录下与root直接相连的 对象
  2. 并发标记:垃圾回收和用户线程同时进行,采用一个闭包结构存储可达对象,记录引用更新。
  3. 重新标记:暂停用户线程,并修正标记期间发生变化的对象的标记记录
  4. 并发清除:开启用户线程,同时进行垃圾回收

优缺点

优点:

  1. 并发收集
  2. 停顿时间短

缺点:

  1. CPU资源敏感
  2. 无法处理浮动垃圾
  3. 标记清除会产生空间碎片

G1收集器