详解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的堆占用阈值。

相关推荐
计算机程序员小杨19 分钟前
计算机专业的你懂的:大数据毕设就选贵州茅台股票分析系统准没错|计算机毕业设计|数据可视化|数据分析
java·大数据
y1y1z23 分钟前
EasyExcel篇
java·excel
DokiDoki之父43 分钟前
多线程—飞机大战排行榜功能(2.0版本)
android·java·开发语言
高山上有一只小老虎1 小时前
走方格的方案数
java·算法
whatever who cares1 小时前
Java 中表示数据集的常用集合类
java·开发语言
JavaArchJourney2 小时前
TreeMap 源码分析
java
whitepure2 小时前
万字详解Java中的IO及序列化
java·后端
还梦呦2 小时前
2025年09月计算机二级Java选择题每日一练——第一期
java·开发语言
与火星的孩子对话2 小时前
Unity高级开发:反射原理深入解析与实践指南 C#
java·unity·c#·游戏引擎·lucene·反射
花开富贵ii2 小时前
代码随想录算法训练营四十六天|图论part04
java·数据结构·算法·图论