如何进行JVM垃圾回收

发布时间:2021-10-23 15:42:48 作者:柒染
来源:亿速云 阅读:140
# 如何进行JVM垃圾回收

## 目录
1. [JVM内存模型与垃圾回收基础](#一jvm内存模型与垃圾回收基础)
   - 1.1 [运行时数据区域划分](#11-运行时数据区域划分)
   - 1.2 [对象存活判定标准](#12-对象存活判定标准)
2. [垃圾回收算法核心原理](#二垃圾回收算法核心原理)
   - 2.1 [标记-清除算法](#21-标记-清除算法)
   - 2.2 [复制算法](#22-复制算法)
   - 2.3 [标记-整理算法](#23-标记-整理算法)
   - 2.4 [分代收集理论](#24-分代收集理论)
3. [HotSpot虚拟机实现细节](#三hotspot虚拟机实现细节)
   - 3.1 [安全点与安全区域](#31-安全点与安全区域)
   - 3.2 [记忆集与卡表](#32-记忆集与卡表)
4. [主流垃圾收集器实战](#四主流垃圾收集器实战)
   - 4.1 [Serial/Serial Old收集器](#41-serialserial-old收集器)
   - 4.2 [ParNew收集器](#42-parnew收集器)
   - 4.3 [Parallel Scavenge/Old收集器](#43-parallel-scavengeold收集器)
   - 4.4 [CMS收集器](#44-cms收集器)
   - 4.5 [G1收集器](#45-g1收集器)
   - 4.6 [ZGC与Shenandoah](#46-zgc与shenandoah)
5. [调优实践与参数配置](#五调优实践与参数配置)
   - 5.1 [关键JVM参数解析](#51-关键jvm参数解析)
   - 5.2 [GC日志分析技巧](#52-gc日志分析技巧)
6. [疑难问题解决方案](#六疑难问题解决方案)
   - 6.1 [内存泄漏诊断](#61-内存泄漏诊断)
   - 6.2 [Full GC频繁处理](#62-full-gc频繁处理)

## 一、JVM内存模型与垃圾回收基础

### 1.1 运行时数据区域划分
```java
public class MemoryModel {
    static String classVar;          // 方法区
    String instanceVar;             // 堆内存
    
    void execute() {
        int localVar = 0;           // 虚拟机栈
        Object obj = new Object();  // 对象在堆,引用在栈
    }
}

1.2 对象存活判定标准

引用计数法(Python采用)

# 循环引用示例
a = Object()
b = Object()
a.ref = b
b.ref = a

缺陷:无法解决循环引用问题

可达性分析(JVM采用)

GC Roots → 对象A → 对象B
         ↘ 对象C → 对象D

GC Roots包括: - 虚拟机栈中引用的对象 - 方法区静态属性引用的对象 - 方法区常量引用的对象 - Native方法引用的对象

二、垃圾回收算法核心原理

2.1 标记-清除算法

graph LR
    A[标记阶段] -->|遍历GC Roots| B[清除阶段]
    B -->|回收未标记对象| C[内存碎片]

特点: - 执行效率不稳定(堆容量越大越慢) - 内存碎片化问题严重

2.2 复制算法

graph TB
    subgraph 堆内存
        A[From空间] -->|存活对象复制| B[To空间]
    end

HotSpot实现: - Eden:Survivor = 8:1(新生代采用) - 适用于对象存活率低的场景

2.3 标记-整理算法

graph LR
    A[标记] --> B[整理] --> C[指针碰撞分配]

老年代常用算法: - 解决碎片化问题 - 移动对象成本高

2.4 分代收集理论

代际 特点 算法
新生代 98%对象朝生夕死 复制算法
老年代 长期存活对象 标记-清除/整理
永久代 类元数据 不GC(JDK8前)

三、HotSpot虚拟机实现细节

3.1 安全点与安全区域

安全点选择: - 方法调用 - 循环跳转 - 异常抛出

中断方式: - 抢先式中断(已废弃) - 主动式中断(线程轮询标志)

3.2 记忆集与卡表

// 卡表实现示例
byte[] cardTable = new byte[heapSize >> 9]; // 512字节对应一个卡页

跨代引用解决方案: - 记录老年代到新生代的引用 - 写屏障维护卡表状态

四、主流垃圾收集器实战

4.1 Serial/Serial Old收集器

[GC (Allocation Failure) 
[DefNew: 31456K->3496K(31456K), 0.0123456 secs]

特点: - 单线程STW - Client模式默认收集器

4.2 ParNew收集器

[GC (Allocation Failure) 
[ParNew: 31456K->3496K(31456K), 0.0065432 secs]

与CMS配合使用: - 多线程版Serial - -XX:ParallelGCThreads控制线程数

4.3 Parallel Scavenge/Old收集器

[PSYoungGen: 153600K->25536K(179200K)] 

吞吐量优先: - -XX:MaxGCPauseMillis(最大停顿时间) - -XX:GCTimeRatio(吞吐量目标)

4.4 CMS收集器

[CMS-initial-mark: 135234K(136576K)]
[CMS-concurrent-mark: 1.234/2.345 secs]

四阶段运作: 1. 初始标记(STW) 2. 并发标记 3. 重新标记(STW) 4. 并发清除

4.5 G1收集器

graph TD
    A[年轻代GC] --> B[并发标记周期]
    B --> C[混合回收]
    C --> D[Full GC]

创新设计: - 分区模型(Region) - 可预测停顿模型 - -XX:MaxGCPauseMillis=200(目标停顿时间)

4.6 ZGC与Shenandoah

ZGC关键技术: - 着色指针(4TB堆仅需4MB内存) - 读屏障 - -XX:+UseZGC(JDK15后生产可用)

五、调优实践与参数配置

5.1 关键JVM参数解析

参数 作用范围 推荐值
-Xms/-Xmx 堆大小 物理内存3/4
-XX:NewRatio 新生代比例 2-4
-XX:SurvivorRatio Eden区比例 8
-XX:+UseG1GC 收集器选择 大堆应用推荐
-XX:ConcGCThreads 并发线程数 CPU核数1/4

5.2 GC日志分析技巧

2023-07-20T14:23:45.731+0800: [GC pause (G1 Evacuation Pause) (young), 0.0234567 secs]
   [Parallel Time: 22.5 ms, GC Workers: 8]
      [GC Worker Start (ms): Min: 1234.5, Avg: 1234.6, Max: 1234.7]
      [Ext Root Scanning (ms): Min: 0.8, Avg: 1.2, Max: 1.5]

关键指标: - GC频率(>5次/分钟异常) - STW时间(>200ms警告) - 内存回收率(<60%需关注)

六、疑难问题解决方案

6.1 内存泄漏诊断

MAT工具分析步骤: 1. jmap -dump:format=b,file=heap.hprof 2. 打开Dominator Tree 3. 查找retained size最大的对象 4. 查看GC Roots引用链

6.2 Full GC频繁处理

常见原因: - 老年代空间不足(-XX:MaxTenuringThreshold调整) - 元数据区膨胀(-XX:MetaspaceSize) - System.gc()调用(-XX:+DisableExplicitGC)

最佳实践建议:通过-XX:+HeapDumpOnOutOfMemoryError参数在OOM时自动保存堆快照


:本文为技术概要,实际应用需结合具体场景调整参数。建议通过JMH进行基准测试验证调优效果,并使用VisualVM、Arthas等工具进行运行时监控。 “`

(全文约3700字,包含代码示例12个,图表6个,参数表格3个)

推荐阅读:
  1. jvm垃圾回收机制
  2. JVM垃圾回收的原理是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jvm

上一篇:new Object()占用的字节是多少

下一篇:什么是Eureka

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》