JVM(2) 垃圾回收

垃圾回收

1、如何判断对象是垃圾

  • 引用计数法 (有该对象引用,计数加一《存在循环引用》)
  • 可达性分析算法(判断是否可由根对象GC Root直接或间接引用《葡萄串》)
  • 可以作为 GC Root 的对象
    • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • 本地方法栈中 JNI(即一般说的Native方法)引用的对象

四种引用:

  • 强引用
  • 软引用(在垃圾回收后内存仍不足时会再次回收软引用对象)
  • 弱引用(垃圾回收时,都会回收弱引用对象)
  • 虚引用(主要配合 ByteBuffer 使用,释放直接内存)

2、垃圾回收算法

1)标记清除

定义:Mark Sweep

  • 速度较快
  • 会产生内存碎片
2)标记整理

Mark Compact

  • 速度慢
  • 没有内存碎片
3)复制 (新生代—>98%都是朝生夕死

Copy

  • 不会有内存碎片
  • 需要占用两倍内存空间
4)分代回收

img

  • 新创建的对象首先分配在 eden 区
  • 新生代空间不足时,触发 minor gc ,eden 区 和 from 区存活的对象使用 - copy 复制到 to 中,存活的对象寿命加一,然后交换 from to
  • minor gc 会引发 stop the world,暂停其他线程,等垃圾回收结束后,恢复用户线程运行
  • 当幸存区对象的寿命超过阈值15 ,会晋升到老年代
  • 当老年代空间不足时,会先触发 minor gc,如果空间仍然不足,那么就触发 full gc ,stop the world 的时间更长!

3、垃圾回收器

1) Serial 收集器(串行)

特点:单线程、简单高效(与其他收集器的单线程相比),采用复制算法。对于限定单个 CPU 的环境来说,Serial 收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。收集器进行垃圾回收时,必须暂停其他所有的工作线程,直到它结束(Stop The World)!

2) Parallel GC收集器(高吞吐量)

特点:属于新生代收集器也是采用复制算法的收集器(用到了新生代的幸存区),又是并行的多线程收集器(与 ParNew 收集器类似)

该收集器的目标是达到一个可控制的吞吐量。还有一个值得关注的点是:GC自适应调节策略GCTimeRatio(与 ParNew 收集器最重要的一个区别)

3)CMS 收集器(低延迟)

在这里插入图片描述

Concurrent Mark Sweep,一种以获取最短回收停顿时间为目标的老年代收集器
特点:基于标记-清除算法实现。并发收集、低停顿,但是会产生内存碎片

CMS 收集器的运行过程分为下列4步:

  • 初始标记 标记 GC Roots 能直接到的对象
  • 并发标记 进行 GC Roots Tracing 的过程
  • 重新标记(时间长) 为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录==(扫描整个堆内存)==
  • 并发清除 对标记的对象进行清除回收,清除的过程中,可能仍然会有新的垃圾产生,这些垃圾就叫浮动垃圾,如果当用户需要存入一个很大的对象时,新生代放不下去,老年代由于浮动垃圾过多,就会退化为 serial Old 收集器

CMS 收集器有三个缺点:

  • 对CPU资源敏感 (并发通病)
  • 无法处理浮动垃圾 —> 退化为 serial Old 收集器
  • Mark Sweep —> 产生内存碎片 —> Full gc

CMS 收集器的内存回收过程是与用户线程一起并发执行的,可以搭配 ParNew 收集器(多线程,新生代,复制算法)与 Serial Old 收集器(单线程,老年代,标记-整理算法)使用。

4)G1 (First)收集器(低延迟)
在这里插入图片描述

特点:思想上的改变。G1将堆内存“化整为零”,将堆内存划分成多个大小相等独立区域Region。(给它制定KPI(要求在任意1秒的时间内,STW停顿不得超过10ms)。G1会尽量达成这个目标,它能够反向推算出本次要收集的大体区域,以增量的方式完成收集。)

  • 不会产生内存碎片(标记-整理+局部看复制)
  • 可预测的停顿
  • 建立Region回收价值列表,每次==优先回收价值最大(First)==Region
  • 每个Region对应一个Remembered Set:
    • 对Region中引用类型数据写操作时,产生Write Barrier 屏障,检查引用对象是否在其他Region中:
      • 若是,通过卡表CartTable将引用信息记录到被引用对象Region的Remembered Set中
    • 以此来避免当对象引用不同Region对象时的全堆扫描

G1的运行过程与CMS大体一致,分为四步:

  • 初始标记 仅标记GC Roots能直接关联到的对象
  • 并发标记 GC Root开始对堆中对象可达性分析
  • 最终标记 短暂的处理遗留下的漏标对象
  • 筛选回收:各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多个收集器线程并行完成的。

4、GC调优

调优思路:

  • 选择适合的垃圾回收器
  • 考虑是否将不必要的对象加载进内存了
  • 是否存在内存泄漏(软、弱引用,缓存)
  • 优先在新生代开始GC(调大新生代占25%-50%)
  • 新生代时间主要耗费在复制

调优案例:

  • GC频繁:加大新生代内存,提高晋升阈值
  • (CMS)单次GC暂停时间长:在重新标记前在新生代先回收一次;
  • (jdk7)老年代充足发生FullGC:加大永久代。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值