读书笔记之《实战Java虚拟机》(5):垃圾收集器和内存分配

本文介绍了Java的多种垃圾回收器,包括串行、并行、CMS和G1回收器,阐述了它们的特点、使用参数。还提及对象晋升老年代的条件、TLAB的作用及使用注意事项,指出应避免使用finalize()方法,最后给出了实战调优的建议,如调整堆大小、选择回收器等。

串行回收器

使用单线程进行垃圾回收,在 CPU 等硬件不是特别优越情况下,性能较好。

-XX:+UseSerialGC 指定使用新生代串行收集器和老年代串行收集器。

并行回收器

在串行回收器基础上做了改进,使用多个线程同时进行垃圾回收,对于并行能力强的计算机,有效缩短垃圾回收所需时间。

  • -XX:+UseParNewGC: 新生代使用 ParNew 回收器
  • -XX:+UseParallelGC: 新生代使用 ParallelGC 回收器
  • -XX:ParallelGCThreads: 指定回收器工作线程数量,推荐为CPU数量

ParallelGC 回收器支持自适应 GC 调节策略,使用 -XX:+UseAdaptiveSizePolicy 可以打开自适应 GC 策略。该策略下,新生代大小、eden 和 survivior 的比例、晋升老年代的年龄等参数会被自动调整,以达到在对大小、吞吐量和停顿之间的平衡点。

CMS 回收器

主要步骤有:初始标记、并发标记、预清理、重新标记、并发清除和并发重置。其中只有初始标记和重新标记会产生STW,从而整体来说,CMS 回收器不是独占式的。

  • -XX:+UseConcMarkSweepGC: 启用CMS 回收器
  • -XX:ConcGCThreads: 指定并发线程数量
  • -XX:+UseCMSCompactAtFullCollection: 使CMS 在垃圾收集完成后,进行一次内存碎片整理
  • -XX:+CMSFullGCsBeforeCompaction: 设定进行多少次 CMS 回收后,进行一次内存碎片整理

G1 回收器

Garbage-First 是 JDK 1.7 正式使用的全新垃圾回收器。

  • 并行性:多个 GC 线程同时工作,有效利用多核计算能力
  • 并发性:可以与应用程序交替执行,不会在整个回收期间完全阻塞应用程序
  • 分代 GC:同时兼顾年轻代和老年代
  • 空间整理:每次回收过程中,适当移动对象,减少空间碎片
  • 可预见性:由于分区的原因,G1 可以部分回收,较好控制STW

四个阶段:

  1. 新生代 GC;
  2. 并发标记周期;
  3. 混合收集;
  4. 如果需要,可能会进行 Full GC;

  • -XX:+UseG1GC:打开 G1 收集器
  • -XX:ParallelGCThreads: 指定回收器工作线程数量,推荐为CPU数量

晋升老年代

  • 对象年龄,也就是经历 GC 次数,默认为15,通过 -XX:MaxTenuringThreshold 设置
  • 大对象,新生代 eden 或者 survivor 都无法容纳这个对象

TLAB

Thread Local Allocation Buffer,线程本地分配缓存,加速对象分配,提高效率,默认开启。

  • -XX:+UseTLAB:启用 TLAB
  • -XX:+PrintTLAB:观察 TLAB 使用情况

注意禁用逃逸分析 -XX:-DoEscapeAnalysis,避免栈上分配影响结果。

TLAB: gc thread: 0x000000000926d000 [id: 13928] desired_size: 337KB slow allocs: 0  refill waste: 5400B alloc: 0.99998    13354KB refills: 1 waste 17.8% gc: 61456B slow: 0B fast: 0B
TLAB: gc thread: 0x00000000091e3800 [id: 2312] desired_size: 337KB slow allocs: 3  refill waste: 5400B alloc: 0.99998    13354KB refills: 3 waste 33.8% gc: 346024B slow: 4784B fast: 0B
TLAB: gc thread: 0x0000000007b03000 [id: 13072] desired_size: 337KB slow allocs: 0  refill waste: 5400B alloc: 0.99998    13354KB refills: 1 waste 99.9% gc: 345616B slow: 0B fast: 0B
TLAB: gc thread: 0x00000000019fd800 [id: 7972] desired_size: 337KB slow allocs: 7  refill waste: 5592B alloc: 0.99998    13354KB refills: 4 waste 18.3% gc: 252864B slow: 344B fast: 0B
TLAB totals: thrds: 4  refills: 9 max: 4 slow allocs: 10 max 7 waste: 32.5% gc: 1005960B max: 346024B slow: 5128B max: 4784B fast: 0B max: 0B
复制代码

对象分配流程图:

finalize()

用于在对象被回收时,进行资源释放。普遍认为,尽量避免使用 finalize() 方法:

  1. finalize() 可能导致对象复活;
  2. 执行时间没有保障,完全由 GC 线程决定;
  3. 糟糕的 finalize() 方法会严重影响 GC 性能;

实战调优

  1. 调整初始堆、最大堆大小;
  2. 选择先进回收器;
  3. 升级服务器、JDK 版本;

转载于:https://juejin.im/post/5c939e1cf265da60ea145f41

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值