第三章、垃圾收集器与内存回收策略

概述

如何判断对象是否可回收
  1. 引用计数法
    通过一个内置的计数器,如果有引用,计数器+1,引用失效,计数器-1.
    优点:实现简单,判定高效。
    缺点: 无法解决循环引用的问题
  2. 可达性分析
    通过GC Roots作为起点,向下搜索,走过的路径成为引用链,没有和引用链关联的对象,可以回收。
    优点:解决循环引用的问题。
    缺点:会造成STW,造成停顿。
可以作为GC Roots的对象:主要是全局性引用和上下文引用。
虚拟机栈中引用的对象;本地方法栈中引用的对象;
方法区类静态属性引用对象,方法区常量引用对象。
引用的分类

强引用:使用new关键字,始终不会被回收。
软引用:在内存不足时,会被回收。
弱引用:在下一次垃圾回收时,会被回收。
虚引用:只用来回收时做一个通知。

垃圾回收过程

在进行可达性分析后,如果一个对象没有和GC Roots相连,则会被第一次标记并进行筛选。
筛选是否执行过finalize()方法,如果对象没有执行过finalize()方法或没有覆写finalize()方法,则没必要执行,否则执行。
有必要执行finalize()方法的对象会放入一个F-Queue的队列,虚拟机有个低优先级线程执行F-Queue队列中对象finalize()方法。
如果执行finalize()方法时,重新和引用链关联起来,在第二次标记时则会被移出即将回收队列,否则将会被回收。

finalize()方法只会被虚拟机执行一次。尽量避免覆写finalize()方法。
回收方法区

需要回收的内容:无用的类和废弃常量。

如何判断常量可回收:没有任何地方引用。

如何判断类可回收:实例被回收;ClassLoader被回收;Class对象没有引用。

安全点和安全区

安全点:特定位置存放OopMap的位置,称为安全点。只有到达安全点,线程才可以暂停。

OopMap:记录对象中哪些时引用记录下来的数据结构。

线程暂停的方式有:主动式中断和抢先式中断。
抢先式中断:不需要线程配合,直接中断所有线程,不在安全点的线程继续运行,直到它到安全点。
主动式中断:设置标志位,线程主动轮询。

安全区:安全区是一个代码段,引用关系不发生变化,在代码段中任意地方GC都是安全的。
是为没有分配CPU时间的休眠或阻塞的线程准备的,线程执行到安全区,会标识自己进入安全区。
GC是,不需要管理进入安全区的线程,当线程要离开时会检查是否可离开,不可离开就等待离开信号。

垃圾回收算法

  1. 标记-清除算法
    先标记,标记完成后,统一清理。
    缺点:效率低,容易产生空间碎片。
  2. 标记-整理算法
    先标记,移动存活对象到一端,边界以外的对象清除掉。
  3. 复制算法
    将内存划分为两块,始终其中一块,当一块用完,将存活对象复制到另一块,将使用过的内存清理掉。
    优点:简单高效,实现简单。
    缺点:可用内存缩小,如果对象存活率较高,就需要进行较多的复制,效率量产。
  4. 分代收集算法
    根据需要将内存划分成不同的区域,根据存活情况,使用不同的回收算法。

垃圾回收器

新生代收集器

新生代收集器都使用复制算法。

  1. Serial收集器
    回收区域:JDK1.3之前新生代默认收集器
    是否多线程:单线程收集器
  2. ParNew收集器
    回收区域:新生代
    是否多线程:多线程收集器
只有它可以与cms配合工作,开启收集线程数和cpu数相同。
  1. Parallel Scavenge
    回收区域:新生代
    是否多线程:多线程收集器
吞吐量 = 执行用户代码时间 / 运行总时间。
paraller scavenge收集器是吞吐量优先收集器。适合后台运算,不需要太多交互的任务。
具有GC自适应的调节策略。
老年代收集器
  1. Serial Old
    回收区域:老年代
    是否多线程:单线程收集器
    回收算法:标记-整理算法。
  2. Parallel Old
    回收区域:老年代
    是否多线程:多线程收集器
    回收算法:标记-整理算法。
  3. CMS收集器
    回收区域:老年代
    是否多线程:多线程收集器
    回收算法:标记-清除算法。
以最短停顿时间为目标。
初始标记→并发标记→重新标记→并发清除
初始标记:标记可以直接关联GC Roots的对象。
并发标记:进行可达性分析。
重新标记:修正运行中的变动。
缺点:
1. 对CPU资源敏感,默认线程数是(CPU数量 + 3) / 4,如果cpu数量小于4个,对资源占用很大。
2. 无法回收浮动垃圾,标记后又产生的垃圾,称为浮动垃圾,CMS无法处理。还要预留空间给用户线程执行。
3. 会产生空间碎片。
G1收集器

G1可以完成整个堆的垃圾回收。整体看使用标记-整理算法,局部使用复制算法,避免了空间碎片。
G1还能建立可预测的停顿时间的模型,能让使用者明确指定一个长度为M毫秒的时间片内,垃圾回收不超过N毫秒。
为什么G1可以建立可预测的停顿?

将内存区域划分成大小相等的独立Region,跟踪每个Region回收价值的大小,维护一个列表,优先回收价值达的Region。

回收过程:
初始标记→并发标记→最终标记→筛选回收。

GC日志格式:
发生时间:[GC类型 [GC区域:GC前大小→GC后大小(该区域总容量), GC耗时] GC前堆大小→GC后堆大小(堆总容量), GC耗时]

内存分配与回收策略

  1. 对象优先分配在Eden区,空间不足进行Minor GC。
  2. 大对象直接进入老年代。
  3. 长期存活对象进入老年代,每个对象都有年龄,每经历一次Minor GC,年龄+1,到达一年年龄,进入老年代。
  4. 动态年龄判断,Survivor中相同年龄对象大小综合超过Survivor一半,则直接进入老年代。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值