Java学习第六十部分——JVM

目录

[一. 关键概述](#一. 关键概述)

[二. 核心功能](#二. 核心功能)

[三. 组成架构](#三. 组成架构)

[1. 类加载子系统 (ClassLoader)](#1. 类加载子系统 (ClassLoader))

[2. 运行时数据区 (Runtime Data Areas)](#2. 运行时数据区 (Runtime Data Areas))

[3. 执行引擎 (Execution Engine)](#3. 执行引擎 (Execution Engine))

[四. 类加载机制](#四. 类加载机制)

[五. 垃圾回收 (GC)](#五. 垃圾回收 (GC))

[六. JIT 编译器 (Just-In-Time)](#六. JIT 编译器 (Just-In-Time))

[七. 调优参数示例](#七. 调优参数示例)

[八. 常见问题与工具](#八. 常见问题与工具)

[九. 与 JDK/JRE 的关系](#九. 与 JDK/JRE 的关系)

[十. 调优与监控](#十. 调优与监控)

[十一. 常见实现](#十一. 常见实现)

[十二. 简单示例](#十二. 简单示例)

[十三. 总结归纳](#十三. 总结归纳)


一. 关键概述

Java 虚拟机(JVM,Java Virtual Machine)是 Java 平台的核心组成部分,负责将编译后的字节码(`.class` 文件)解释或编译为机器码,并在不同操作系统上实现"一次编写,到处运行"(Write Once, Run Anywhere)的跨平台特性。

二. 核心功能

  • **跨平台执行:**将字节码翻译成不同操作系统的本地机器指令。

  • **内存管理:**自动分配/回收内存(堆、栈等),避免手动管理错误。

  • **垃圾回收 (GC):**自动回收无用的对象内存。

  • **字节码执行:**通过解释器或 JIT 编译器执行字节码。

三. 组成架构

1. 类加载子系统 (ClassLoader)
组件 功能描述 关键特性
Bootstrap ClassLoader 加载 JAVA_HOME/lib 的核心类库(如 rt.jar 由 C++ 实现,JVM 自身的一部分
Extension ClassLoader 加载 JAVA_HOME/lib/ext 目录的扩展类库 继承自 URLClassLoader,父加载器为 Bootstrap
Application ClassLoader 加载用户类路径(classpath)的类 默认线程上下文类加载器,父加载器为 Extension
双亲委派模型 加载类时优先委派父类加载器处理 避免核心类被篡改(如自定义 java.lang.String),确保安全性和类唯一性

2. 运行时数据区 (Runtime Data Areas)
内存区域 存储内容 特性
方法区 (Method Area) 类元数据(类名、字段、方法)、常量池、静态变量 JDK 8+ 由元空间 (Metaspace) 实现,使用本地内存,替代永久代(PermGen)
堆 (Heap) 对象实例和数组 垃圾回收主区域 ,分为: - 新生代(Eden + Survivor From/To) - 老年代
虚拟机栈 (JVM Stack) 每个线程私有,存储栈帧(局部变量表、操作数栈、动态链接、方法出口) 方法调用压栈,返回弹栈;可能抛出 StackOverflowError
本地方法栈 服务于 Native 方法(如 JNI 调用的 C/C++ 代码) 与虚拟机栈类似,但针对本地方法
程序计数器 (PC Register) 记录当前线程执行的字节码指令地址 唯一不会发生 OOM 的区域,线程私有

3. 执行引擎 (Execution Engine)
组件 功能描述 关键实现
解释器 (Interpreter) 逐行解释字节码为机器码执行 启动速度快,但运行时效率低
JIT 编译器 将热点代码(高频方法/循环)编译为本地机器码 HotSpot 使用分层编译: - C1 编译器(客户端,快速优化) - C2 编译器(服务端,深度优化)
垃圾回收器 (GC) 自动回收无引用对象的内存 主流算法与收集器 : - 新生代:复制算法 (Parallel Scavenge) - 老年代:标记-清除/整理 (CMS) - G1 GC (JDK9+ 默认):区域化分代 + 可预测停顿 - ZGC(JDK11+):低延迟(<10ms)、TB 级

核心关系总结

  • 类加载 → 运行时数据区:

ClassLoader 加载的类元数据存储于方法区,对象实例分配在堆中。

  • 执行引擎 → 运行时数据区:

解释器/JIT 执行栈中方法的字节码;GC 管理堆内存的回收。

  • 线程私有区域:

每个线程独立拥有:虚拟机栈、本地方法栈、程序计数器。

四. 类加载机制

类加载分三个阶段:
1. **加载 (Loading)**

  • 通过类加载器(`ClassLoader`)加载 `.class` 文件到内存。

  • 类加载器层级:

  • **Bootstrap ClassLoader**(加载核心库如 `rt.jar`)

  • **Extension ClassLoader**(加载扩展库)

  • **Application ClassLoader**(加载用户类路径)

  • **自定义 ClassLoader**(用户扩展)。
    2. **链接 (Linking)**

  • 验证字节码合法性 → 准备(为静态变量分配内存)→ 解析(符号引用转直接引用)。
    3. **初始化 (Initialization)**

  • 执行静态代码块和静态变量赋值(如 `static int x = 10;`)。

五. 垃圾回收 (GC)

- **回收对象**: 无引用指向的对象(如超出作用域的局部变量)。
- **GC 算法**:

  • **分代收集**:堆分为 **新生代 (Young)** 和 **老年代 (Old)**。

  • 新生代:使用 **复制算法**(Eden + Survivor 区)。

  • 老年代:使用 **标记-清除** 或 **标记-整理** 算法。

  • **垃圾收集器**:

  • **Serial GC**:单线程,适合小应用。

  • **Parallel GC**(默认):多线程,吞吐量优先。

  • **CMS** / **G1 GC**:低延迟,减少 STW(Stop-The-World)时间。

  • **ZGC** / **Shenandoah**(JDK 15+):超低延迟(<10ms)。

六. JIT 编译器 (Just-In-Time)

  • **热点代码优化**:频繁执行的字节码会被编译成本地机器码(如循环、高频方法)。

  • **解释器 vs JIT**:解释器逐行执行字节码(启动快);JIT 编译后执行(运行快)。

七. 调优参数示例

堆内存设置

-Xms512m # 初始堆大小(默认物理内存 1/64)

-Xmx1024m # 最大堆大小(默认物理内存 1/4)

-XX:NewRatio=2 # 老年代:新生代 = 2:1

-XX:SurvivorRatio=8 # Eden:Survivor = 8:1

垃圾回收器选择

-XX:+UseG1GC # 启用 G1 收集器

-XX:+UseConcMarkSweepGC # 启用 CMS 收集器

元空间设置(JDK 8+)

-XX:MetaspaceSize=128m

-XX:MaxMetaspaceSize=256m

八. 常见问题与工具

- **内存泄漏**: 对象被意外保留引用(如静态集合类持续增长)。
- **OOM (OutOfMemoryError)**: 堆/元空间不足。
- **诊断工具**:

  • **jconsole** / **VisualVM**:图形化监控堆、线程、类加载。

  • **jstack**:分析线程堆栈(死锁检测)。

  • **jmap**:导出堆内存快照(配合 **MAT** 工具分析内存泄漏)。

  • **jstat**:监控 GC 状态(`jstat -gcutil <pid> 1000`)。

九. 与 JDK/JRE 的关系

  • **JDK (Java Development Kit)**:开发工具包(含 JRE + 编译器 `javac`)。

  • **JRE (Java Runtime Environment)**:运行环境(含 JVM + 基础库)。

  • **JVM**:执行引擎,是 JRE 的子集。

十. 调优与监控

- **常用参数**:

  • 堆大小:`-Xms`(初始堆)、`-Xmx`(最大堆)。

  • 新生代比例:`-XX:NewRatio`。

  • GC 日志:`-Xlog:gc*`(JDK 9+)。

  • 元空间:`-XX:MaxMetaspaceSize`。
    - **监控工具**:

  • **JVisualVM**:可视化监控线程、堆、GC。

  • **JConsole**:实时查看内存、线程、类加载。

  • **jstack**:查看线程堆栈(定位死锁)。

  • **jmap**:生成堆转储(`jmap -dump` 分析内存泄漏)。

十一. 常见实现

  • **HotSpot**(Oracle/OpenJDK 默认):支持 JIT 和多种 GC。

  • **OpenJ9**(IBM):低内存占用,适合云原生。

  • **GraalVM**:多语言支持(Java/Python/JS),原生镜像(AOT 编译)。

十二. 简单示例

java 复制代码
// 内存泄漏示例:静态集合持有对象引用
public class MemoryLeak {
    private static final List<Object> list = new ArrayList<>();
    public void addData() {
        while (true) {
            list.add(new byte[1024 * 1024]); // 持续占用内存
        }
    }
}

排查步骤:

  1. 使用 `jmap -dump:format=b,file=heap.hprof <pid>` 生成堆转储。

  2. 通过 MAT 或 VisualVM 分析泄漏路径(如 `list` 持续增长)。

十三. 总结归纳

JVM 是 Java 生态的基石,理解其内存模型、类加载、GC 机制是优化性能的关键。掌握 JVM 调优和诊断工具,能有效解决内存溢出、高延迟等问题。JVM 通过抽象操作系统差异、自动化内存管理和高效的执行引擎,成为 Java 高性能和跨平台能力的基石。理解其原理和调优技巧,是 Java 开发者进阶的必经之路。

相关推荐
蜡笔小欣丫1 小时前
USB导出功能(QT)
开发语言·qt
阿群今天学习了吗1 小时前
面向对象基础笔记
笔记·学习·算法
凤凰AI1 小时前
Python知识点4-嵌套循环&break和continue使用&死循环
开发语言·前端·python
Dxy12393102161 小时前
Python适配器模式详解:让不兼容的接口协同工作
开发语言·python·适配器模式
是瑶瑶子啦1 小时前
【AlphaFold3】符号说明+Data_pipline学习笔记
人工智能·深度学习·学习
真的想上岸啊1 小时前
学习C++、QT---27(QT中实现记事本项目实现行列显示、优化保存文件的功能的讲解)
c++·qt·学习
今晚打老虎1 小时前
让黑窗口变彩色:C++控制台颜色修改指南
开发语言·c++
余很多之很多2 小时前
借助AI学习开源代码git0.7之四update-cache
git·学习
Murphy_lx2 小时前
C++中的list(1)
开发语言·c++·list
lemon_sjdk2 小时前
LWJGL教程(2)——游戏循环
java·人工智能·算法·游戏