串行回收器
使用单线程进行垃圾回收,在 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
四个阶段:
- 新生代 GC;
- 并发标记周期;
- 混合收集;
- 如果需要,可能会进行 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() 方法:
- finalize() 可能导致对象复活;
- 执行时间没有保障,完全由 GC 线程决定;
- 糟糕的 finalize() 方法会严重影响 GC 性能;
实战调优
- 调整初始堆、最大堆大小;
- 选择先进回收器;
- 升级服务器、JDK 版本;