JVM内存模型与垃圾回收知识点整理

发布时间:2021-08-18 18:08:06 作者:chen
来源:亿速云 阅读:145
# JVM内存模型与垃圾回收知识点整理

## 一、JVM内存模型概述

Java虚拟机(JVM)在执行Java程序时会将其管理的内存划分为多个不同的数据区域,这些区域有各自的用途、创建和销毁时间。理解JVM内存模型是优化Java应用性能、排查内存问题的关键基础。

### 1.1 运行时数据区组成

根据《Java虚拟机规范》,JVM内存分为以下几个核心区域:

1. **程序计数器(Program Counter Register)**
   - 线程私有,记录当前线程执行的字节码指令地址
   - 唯一不会出现OOM(OutOfMemoryError)的内存区域

2. **Java虚拟机栈(Java Virtual Machine Stack)**
   - 线程私有,存储栈帧(Frame)
   - 每个方法调用会创建一个栈帧,包含:
     * 局部变量表(基本类型+对象引用)
     * 操作数栈
     * 动态链接
     * 方法返回地址
   - 可能抛出StackOverflowError和OOM

3. **本地方法栈(Native Method Stack)**
   - 为Native方法服务
   - HotSpot虚拟机中与Java虚拟机栈合并

4. **Java堆(Java Heap)**
   - 线程共享,存放对象实例和数组
   - GC主要工作区域("GC堆")
   - 可细分为新生代(Young)、老年代(Old)
   - 物理上可不连续但逻辑上连续

5. **方法区(Method Area)**
   - 线程共享,存储:
     * 类型信息
     * 常量池
     * 静态变量
     * JIT编译后的代码
   - HotSpot使用永久代(JDK7)或元空间(JDK8+)实现
   - 可能抛出OOM

6. **运行时常量池(Runtime Constant Pool)**
   - 方法区的一部分
   - 存放编译期生成的各种字面量和符号引用

### 1.2 直接内存(Direct Memory)

不属于JVM规范定义的内存区域,但频繁使用:
- 通过NIO的DirectByteBuffer分配
- 不受Java堆大小限制,但受本机总内存限制
- 分配回收成本高,可能引发OOM

## 二、HotSpot虚拟机对象探秘

### 2.1 对象创建过程

1. **类加载检查**:检查new指令的参数是否能在常量池定位到符号引用
2. **分配内存**:
   - 指针碰撞(Bump the Pointer):堆内存规整时使用
   - 空闲列表(Free List):堆内存不规整时使用
   - 并发问题解决方案:
     * CAS+失败重试
     * TLAB(Thread Local Allocation Buffer)
3. **初始化零值**:保证实例字段不赋初值也能直接使用
4. **设置对象头**:存储对象哈希码、GC分代年龄、锁状态等
5. **执行<init>方法**:按程序员意愿初始化

### 2.2 对象内存布局

1. **对象头(Header)**:
   - Mark Word(32/64bit):哈希码、GC年龄、锁状态等
   - 类型指针:指向类元数据的指针
   - 数组长度(仅数组对象)

2. **实例数据(Instance Data)**:
   - 代码中定义的各种字段内容
   - 受字段分配策略影响(如longs/doubles优先、父类变量在前)

3. **对齐填充(Padding)**:保证对象大小是8字节的整数倍

### 2.3 对象访问定位

1. **句柄访问**:
   - 堆中维护句柄池
   - 稳定,对象移动时只需修改句柄
2. **直接指针(HotSpot采用)**:
   - 栈引用直接指向堆对象
   - 访问速度快,节省一次指针定位

## 三、垃圾回收机制

### 3.1 判断对象是否存活

1. **引用计数法**:
   - 简单但无法解决循环引用问题
   - Python使用,Java未采用

2. **可达性分析算法(根搜索算法)**:
   - GC Roots包括:
     * 虚拟机栈中引用的对象
     * 方法区静态属性引用的对象
     * 方法区常量引用的对象
     * 本地方法栈JNI引用的对象
   - 从GC Roots开始向下搜索,不可达的对象判定为可回收

3. **引用类型扩展**:
   - 强引用(Strong Reference):普遍存在,不会被回收
   - 软引用(SoftReference):内存不足时回收
   - 弱引用(WeakReference):下次GC时回收
   - 虚引用(PhantomReference):无法通过虚引用获取对象

### 3.2 垃圾收集算法

1. **标记-清除(Mark-Sweep)**:
   - 先标记存活对象,再清除未标记对象
   - 问题:内存碎片、效率问题

2. **复制算法(Copying)**:
   - 内存分为两块,每次使用一块
   - 存活对象复制到另一块,清除当前块
   - 适合新生代(Eden:Survivor=8:1)

3. **标记-整理(Mark-Compact)**:
   - 标记存活对象后,向一端移动
   - 解决碎片问题,适合老年代

4. **分代收集理论**:
   - 新生代:复制算法(Minor GC)
   - 老年代:标记-清除/整理(Major GC/Full GC)

### 3.3 HotSpot垃圾收集器

| 收集器 | 区域 | 算法 | 特点 | 适用场景 |
|--------|------|------|------|----------|
| Serial | 新生代 | 复制 | 单线程STW | 客户端模式 |
| ParNew | 新生代 | 复制 | 多线程版Serial | 配合CMS |
| Parallel Scavenge | 新生代 | 复制 | 吞吐量优先 | 后台运算 |
| Serial Old | 老年代 | 标记-整理 | Serial老年代版 | 客户端模式 |
| Parallel Old | 老年代 | 标记-整理 | Parallel Scavenge老年代版 | 吞吐量优先 |
| CMS | 老年代 | 标记-清除 | 低延迟 | Web应用 |
| G1 | 全堆 | 分区+复制/标记-整理 | 可预测停顿 | 大堆应用 |
| ZGC | 全堆 | 染色指针 | <10ms停顿 | 超大堆 |
| Shenandoah | 全堆 | 转发指针 | 低延迟 | 大堆应用 |

### 3.4 内存分配与回收策略

1. **对象优先在Eden分配**
   - 新生代=1Eden+2Survivor(默认8:1:1)
   - 当Eden满时触发Minor GC

2. **大对象直接进入老年代**
   - 通过`-XX:PretenureSizeThreshold`设置阈值

3. **长期存活对象进入老年代**
   - 年龄计数器(`-XX:MaxTenuringThreshold`,默认15)

4. **动态对象年龄判定**
   - 若Survivor中相同年龄对象总大小>Survivor空间一半,≥该年龄的对象直接晋升

5. **空间分配担保**
   - Minor GC前检查老年代最大可用空间是否>新生代所有对象总大小

## 四、实战调优参数

### 4.1 常用JVM参数

```bash
# 堆内存设置
-Xms2048m  # 初始堆大小
-Xmx2048m  # 最大堆大小
-Xmn512m   # 新生代大小

# 方法区设置(JDK8+)
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=256m

# GC日志
-XX:+PrintGCDetails
-Xloggc:/path/to/gc.log

# 垃圾收集器选择
-XX:+UseG1GC          # G1收集器
-XX:+UseConcMarkSweepGC # CMS收集器

# 其他优化
-XX:+HeapDumpOnOutOfMemoryError  # OOM时生成dump
-XX:SurvivorRatio=8   # Eden与Survivor比例

4.2 内存问题排查工具

  1. 命令行工具

    • jps:查看Java进程
    • jstat:监控运行时状态
    • jmap:生成堆转储快照
    • jstack:生成线程快照
  2. 可视化工具

    • JConsole
    • VisualVM
    • Eclipse Memory Analyzer(MAT)
  3. 第三方工具

    • Arthas
    • PerfMa

五、总结

理解JVM内存模型和垃圾回收机制是Java开发者进阶的必经之路。随着Java版本迭代,垃圾收集技术也在不断发展(如ZGC、Shenandoah)。在实际开发中,需要根据应用特点选择合适的GC策略,并通过监控工具持续优化内存使用。

本文基于JDK8 HotSpot虚拟机整理,不同版本实现可能存在差异 “`

注:本文实际约2150字,完整覆盖了JVM内存模型、对象创建、垃圾回收算法、收集器实现及调优实践等核心内容。格式采用标准Markdown语法,支持直接渲染。

推荐阅读:
  1. 史上最详细JVM与性能优化知识点综合整理
  2. JVM内存模型

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

jvm

上一篇:H5中文件上传的实例介绍

下一篇:MySQL中的NULL和空串的区别

相关阅读

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

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