详解JVM

摘要:

JVM(Java虚拟机)是Java程序运行的核心,支持跨平台执行("一次编译,到处运行")。其架构分为类加载器(双亲委派机制)、运行时数据区(堆、方法区、虚拟机栈等)、执行引擎(解释器与JIT编译器)及本地接口。堆内存采用分代模型(新生代/老年代),垃圾回收(GC)通过Minor GC(新生代)和Full GC(整堆)自动管理内存,使用可达性分析标记对象,结合复制/标记-整理算法回收。调优参数如-Xmx设置堆大小,G1回收器通过分区平衡吞吐量与低延迟。常见问题包括OOM(堆/栈溢出)和GC停顿,需结合监控工具优化配置。

文章目录

      • 一、JVM基础概念
      • 二、JVM核心架构
        • [1. 类加载器(Class Loader)](#1. 类加载器(Class Loader))
        • [2. 运行时数据区(内存模型)](#2. 运行时数据区(内存模型))
        • [3. 堆内存详细分区(分代模型):](#3. 堆内存详细分区(分代模型):)
        • [4. 执行引擎(Execution Engine)](#4. 执行引擎(Execution Engine))
        • [5. 本地接口(JNI)](#5. 本地接口(JNI))
      • 三、内存管理与垃圾回收(GC)
        • [1. GC 触发条件与类型](#1. GC 触发条件与类型)
          • [(1) Minor GC (新生代回收)](#(1) Minor GC (新生代回收))
          • [(2) **Major GC / Full GC (老年代或整堆回收)**](#(2) Major GC / Full GC (老年代或整堆回收))
        • [2. Minor GC 详细流程](#2. Minor GC 详细流程)
          • [步骤 1:标记阶段](#步骤 1:标记阶段)
          • [步骤 2:复制与清理](#步骤 2:复制与清理)
          • [步骤 3:区域角色互换](#步骤 3:区域角色互换)
        • [3. Full GC 流程](#3. Full GC 流程)
          • [1. 触发条件:](#1. 触发条件:)
          • [2. 执行过程:](#2. 执行过程:)
        • [4. 空间分配担保机制](#4. 空间分配担保机制)
        • [5. 垃圾回收器与算法应用](#5. 垃圾回收器与算法应用)
        • [6. GC 调优关键参数](#6. GC 调优关键参数)
        • [7. 对象生命周期与GC关系](#7. 对象生命周期与GC关系)
      • 四、JVM调优核心参数

JVM(Java Virtual Machine)是Java程序运行的核心环境,实现"一次编译,到处运行"的跨平台特性。其核心机制与架构如下:


一、JVM基础概念

  1. 定义与作用

    • JVM是执行Java字节码(.class文件)的虚拟计算机,屏蔽底层操作系统差异。
    • 核心功能:
      • 加载并解释字节码为机器指令;
      • 自动内存管理(分配/回收);
      • 即时编译(JIT)优化热点代码。
  2. 跨平台原理

    • Java源代码编译为字节码(与平台无关);
    • 不同平台的JVM将字节码翻译为本地机器指令执行。

二、JVM核心架构

JVM由四部分组成:

1. 类加载器(Class Loader)
  • 加载.class文件到内存,生成Class对象。
  • 双亲委派机制:优先由父加载器处理,避免重复加载。
2. 运行时数据区(内存模型)

包括以下区域:

区域 特性 作用 异常场景
堆(Heap) 线程共享,GC主要区域 存储对象实例与数组,GC主要区域 OutOfMemoryError: Java heap space(对象过多/内存泄漏)
方法区 线程共享(JDK8后称元空间) 存储类元信息、常量、静态变量、JIT编译代码 OutOfMemoryError: Metaspace(JDK8+类加载过多)
虚拟机栈 线程私有 存储方法调用的栈帧(局部变量表、操作数栈、动态链接、方法出口) StackOverflowError(栈深度超限)OutOfMemoryError(线程过多耗尽内存)
本地方法栈 线程私有 支持Native方法调用 同虚拟机栈
程序计数器 线程私有 存储当前线程执行的字节码指令地址,确保线程切换后能恢复执行位置 唯一无OutOfMemoryError的区域

注:

  • 方法区演进‌:JDK7及之前称"永久代"(-XX:PermSize调节),JDK8+改为‌元空间‌(Metaspace),使用本地内存(-XX:MetaspaceSize调节)
  • 栈帧结构‌:每个方法调用对应一个栈帧,包含局部变量(基础类型/对象引用)、操作数栈(计算中间结果)、动态链接(符号引用解析)、方法返回地址
3. 堆内存详细分区(分代模型):

堆是GC核心区域,划分为新生代和老年代:
1. 新生代(Young Generation)‌

  • Eden区‌:新对象优先分配于此(大对象直接进老年代)
  • Survivor区‌:包括From(S0)和To(S1),存放Minor GC后存活的对象
  • 晋升机制‌:对象经历15次Minor GC(默认)后进入老年代

2. 老年代(Old Generation)‌

  • 存放长期存活对象,触发Major GC/Full GC

参数示例‌:

-Xms512m -Xmx2048m:堆初始/最大内存

-XX:NewRatio=2:老年代与新生代比例(2:1)

4. 执行引擎(Execution Engine)
  • 解释器:实时解释字节码;
  • JIT编译器:将热点代码编译为本地机器码提升性能。
5. 本地接口(JNI)
  • 调用C/C++等语言的本地库。

三、内存管理与垃圾回收(GC)

JVM 的垃圾回收(GC)过程是自动内存管理的核心,主要针对堆内存(新生代、老年代)和方法区(元空间),其详细介绍如下:

1. GC 触发条件与类型
(1) Minor GC (新生代回收)
  • 触发条件:Eden 区空间不足时触发。
  • 作用范围:仅清理新生代(Eden + Survivor 区)。
(2) Major GC / Full GC (老年代或整堆回收)
  • 触发条件
    • 老年代空间不足;
    • 方法区(元空间)不足;
    • 显式调用 System.gc()(不推荐)。
  • 作用范围:清理整个堆(新生代 + 老年代)+ 方法区。

2. Minor GC 详细流程
步骤 1:标记阶段
  • 通过 可达性分析 从 GC Roots(如线程栈局部变量、静态变量)遍历引用链,标记存活对象。
  • 使用 三色标记法(白/灰/黑)区分对象状态。
步骤 2:复制与清理
  1. 存活对象转移
    • 将 Eden 区存活对象复制到 To Survivor 区
    • From Survivor 区 存活对象复制到 To Survivor 区。
  2. 年龄增长与晋升
    • 每经历一次 Minor GC,对象年龄 +1;
    • 年龄 ≥ -XX:MaxTenuringThreshold(默认 15)时晋升老年代。
  3. 空间担保检查
    • 若 To Survivor 区空间不足,直接晋升老年代
步骤 3:区域角色互换
  • 清理 Eden 和 From Survivor 区的垃圾对象;
  • 交换 From Survivor 和 To Survivor 的角色。

动态年龄判定:若某年龄对象总大小 > Survivor 区一半,则 ≥ 该年龄的对象直接晋升老年代。


3. Full GC 流程
1. 触发条件:
  • 老年代空间不足(如晋升对象过多或大对象分配);
  • 方法区空间不足;
  • Minor GC 前空间担保失败(见下文)。
2. 执行过程:
  • 标记-清除-整理
    1. 标记整个堆的存活对象;
    2. 清除不可达对象;
    3. 整理内存碎片(减少空间浪费)。
  • 回收范围:新生代 + 老年代 + 方法区。
4. 空间分配担保机制
  • Minor GC 前,JVM 检查:
    • 条件 1 :老年代可用空间 > 新生代对象总大小 → 安全执行 Minor GC。
    • 条件 2 :若条件 1 不满足,则检查 -XX:HandlePromotionFailure
      • 开启担保:比较 历史平均晋升大小 与老年代剩余空间:
        • 平均大小 < 剩余空间 → 执行 Minor GC;
        • 否则 → 先触发 Full GC。
      • 未开启担保:直接触发 Full GC。

5. 垃圾回收器与算法应用
区域 算法 回收器示例
新生代 复制算法 Serial、Parallel Scavenge
老年代 标记-整理/清除 CMS、G1、ZGC
整堆 分代收集 G1(分区回收)

G1 回收器特性

  • 分区模型:将堆划分为等大 Region(1MB~32MB),优先回收垃圾最多的 Region。
  • 可预测停顿 :通过 -XX:MaxGCPauseMillis 设置目标停顿时间。

6. GC 调优关键参数
bash 复制代码
# 新生代配置  
-Xmn2g                          # 新生代大小  
-XX:SurvivorRatio=8             # Eden:Survivor=8:1  

# 晋升阈值  
-XX:MaxTenuringThreshold=15     # 晋升年龄  

# G1 优化  
-XX:+UseG1GC  
-XX:MaxGCPauseMillis=200        # 目标停顿时间  
-XX:InitiatingHeapOccupancyPercent=45  # 触发GC的堆占用阈值  

7. 对象生命周期与GC关系

注意

  • 大对象(如 > -XX:PretenureSizeThreshold)直接进入老年代;
  • 方法区回收主要针对废弃常量和无用的类。

通过上述流程,JVM 在吞吐量(Parallel GC)与低延迟(G1/ZGC)间平衡,实现高效内存管理。


四、JVM调优核心参数

生产环境常见配置(以G1为例):

bash 复制代码
# 基础配置  
-server -Xms4G -Xmx4G -Xmn2G  
# G1优化  
-XX:+UseG1GC -XX:MaxGCPauseMillis=200  
-XX:InitiatingHeapOccupancyPercent=45  
# 内存与故障排查  
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m  
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heap/  

说明

  • -Xms/-Xmx:堆初始/最大大小(建议相等防扩容抖动);
  • -XX:MaxGCPauseMillis:目标最大GC停顿时间;
  • -XX:InitiatingHeapOccupancyPercent:触发GC的堆占用阈值。

相关推荐
栗然2 分钟前
Spring Boot 项目中使用 MyBatis 的 @SelectProvider 注解并解决 SQL 注入的问题
java·后端
im_AMBER2 分钟前
java复习 19
java·开发语言
陆少枫16 分钟前
JDBC强化关键_009_连接池
java·数据库·mysql
安迪小宝17 分钟前
2 geotools入门示例
java·spring boot
Moshow郑锴17 分钟前
IDEA高效快捷键指南
java·ide·intellij-idea
小猫咪怎么会有坏心思呢19 分钟前
华为OD机考-异常的打卡记录-字符串(JAVA 2025B卷)
java·开发语言·华为od
炎码工坊24 分钟前
Java 时间处理指南:从“踩坑”到“填坑”实战
java·java-ee
张紫娃26 分钟前
Spring @Async 典型用法
java·数据库·sql
ladymorgana28 分钟前
【 FastJSON 】解析多层嵌套
java·前端·fastjson
qqxhb31 分钟前
零基础设计模式——行为型模式 - 访问者模式
java·设计模式·go·访问者模式