GC 垃圾回收

|▌冷眼眸甩不掉的悲伤 提交于 2020-02-26 14:58:38

1 判断对象是否是垃圾算法

1.1 引用计数算法

  • 优点:执行效率高,程序执行受影响较小
  • 缺点:无法检测出循环引用 情况,导致内存泄漏

1.2 可达性分析算法

  • 通过判断对象的引用链是否可达来决定对象是否可以被回收

1.3 可作为GC Root的对象

  • 虚拟机栈中引用的对象(栈针重点本地变量表)
  • 方法区中的常量引用对象
  • 方法区中的类静态属性引用的对象
  • 本地方法栈中JNI(Native方法)的引用对象
  • 活跃线程的应用对象

2 垃圾回收算法

2.1 标记-清除算法(Mark and Sweep)

  • 标记:从根集合进行扫描,对存活的对象进行标记
  • 清除:对堆内存从头到尾进行线性遍历,回收不可达对象内存

2.2 复制算法(Copying)

  • 解决碎片化问题
  • 顺序分配内存,简单高效
  • 适用于对象存活率低的场景

2.3 标记-整理算法(Compacting)

  • 标记:从根集合进行扫描,对存活的对象进行标记
  • 清除:移动所有存活对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收

总结:

  • 避免内存的不连续性
  • 不用设置两块内存互换
  • 适用于存活率高的场景

2.4 分代收集算法(Generational Collector)

  • 垃圾回收算法的组合拳
  • 按照对象生命周期的不同划分区域以采用不同的垃圾回收算法
  • 目的:提高JVM的回收效率

3 彩蛋

3.1 JVM运行模式

  • Server
  • Client

3.2 Stop-the-world

  • JVM 由于要执行GC而停止了应用程序的执行
  • 任务一种GC算法中都会发生
  • 多数GC优化通过减少Stop-the-world发生的时间来提高程序性能

3.3 Safepoint

  • 分析过程中对象引用关系不会发生变化的点
  • 产生Safepoint的地方:方法调用、循环跳转、异常跳转等
  • 安全点数量要适中

3.4 吞吐量

运行用户代码时间/(运行用户代码时间+垃圾收集时间)

3.5 查看垃圾收集器

java -XX:+PrintCommandLineFlags -version

4 垃圾收集器

  收集器 手机算法
年轻代 Serial 复制算法
  ParNew 复制算法
  Parallel Scavenge 复制算法
老年代 Serial Old 标记-整理算法
  Parallel Old 标记-整理算法
  CMS 标记-清除算法

4.1 年轻代

(1)Serial 收集器

  • 复制算法
  • 单线程收集,进行垃圾收集时,必须暂停所有动作线程
  • 简单高效,Client模式下默认的年轻代收集器

(2)ParNew 收集器

  • 复制算法
  • 多线程收集,其余的行为、特点和Serial收集器一样
  • 单核执行效率不如Serial,在多核下执行才有优势

(3)Parallel Scavenge 收集器

  • 复制算法
  • 比起关注用户线程停顿时间,更关注系统的吞吐量
  • 在多核下执行才有优势,Server模式下默认的年轻代收集器
  • -XX:+UseAdaptiveSizePolicy 自动调节

4.2 老年代

(1)Serial Old 收集器

  • 标记-整理算法
  • 单线程收集,进行垃圾收集时,必须暂停所有工作线程
  • 简单高效,Client模式下默认的老年代收集器

(2)Parallel Old 收集器

  • 标记-整理算法
  • 多线程,吞吐量优先

(3)CMS 收集器

  • 标记-清除算法
  • 希望JAVA垃圾回收器回收垃圾的时间尽可能短,以获取最小停顿时间为目的
  • 应用运行在多CPU的机器上,有足够的CPU资源
  • 有比较多生命周期长的对象
  • 希望应用的响应时间短

CMS 收集过程

【1】初始标记 CMS-initial-mark

stop-the-world,这个阶段会扫描root对象直接关联的可达对象。注意不会递归的追踪下去,只是到达第一层而已。这个过程,会STW,但是时间很短。

【2】并发标记 CMS-concurrent-mark

并发追溯标记,程序不会停顿。

【3】并发预清理

查找执行并发标记阶段从年轻代晋升到老年代的对象。

【4】重新标记 CMS-remark

暂停虚拟机,扫描CMS堆中的剩余对象。在并发mark阶段,应用的线程可能产生新的垃圾,所以需要重新标记,这个阶段也是会STW。

【5】并发清除 CMS-concurrent-sweep

清理垃圾对象,程序不会停顿

【6】并发重置 CMS-concurrent-reset

并发重置状态等待下次CMS的触发

CMS 收集器缺点

【1】Concurrent Mode Failure

由于cms垃圾回收线程可以和应用的线程一起工作,那么应用线程仍然需要申请内存,如果这个时候老年代的空间已经不够用了。那么会有Concurrent Mode Failure 这样的日志输出,之后会进行一次Full GC的操作,所有的应用线程都会停止工作。

【2】浮动垃圾

由于cms垃圾回收线程可以跟应用的线程一起工作,那么应用的线程也会产生垃圾,这些称之为浮动垃圾。

【3】降低吞吐量

由于应用线程和垃圾回收线程一起工作,那么垃圾回收线程也就抢占了系统资源,会对应用的吞吐量造成一定的影响。为了保证垃圾回收过程中,应用线程有足够的内存可以使用,当堆内存的空间使用率达到68%的时候,CMS开始触发垃圾回收。

【4】内存碎片

CMS是基于标记-清除算法的,会造成内存碎片。

4.3 G1 收集器

复制+标记-整理算法

-XX:+UseG1GC

特点:

  • 并行和并发
  • 分代收集
  • 空间整合
  • 可预测的停顿

实现:

  • 将整个java堆内存划分多个大小相等的Region
  • 年轻代和老年代不再物理隔离

4.4 其他收集器

Epsilon GC 和 ZGC(jdk11)

5 收集器设置

【1】XX:+UseSerialGC

虚拟机运行在Client模式下的默认值,Serial+Serial Old

【2】-XX:+UseParNewGC

在JDK1.8被废弃,在JDK1.7还可以使用 ParNew+Serial Old

【3】-XX:+UseParallelOldGC

Parallel Scavenge+Parallel Old

【4】XX:+UseConcMarkSweepGC 互联网应用的选择

ParNew+CMS+Serial Old
Serial Old收集器作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器使用。

【5】-XX:+UseParallelGC 后台应用程序的选择

虚拟机运行在Server模式下的默认值,Parallel Scavenge+Serial Old(PS Mark Sweep)

【6】-XX:+UseG1GC

G1+G1

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!