JVM 深度解析

一、JVM 概述
1.1 什么是 JVM?

JVM(Java Virtual Machine,Java 虚拟机)是 Java 程序运行的核心引擎。它像一个“翻译官”,将 Java 字节码转换为机器能理解的指令,并管理程序运行时的内存、线程等资源。

核心功能

  • 跨平台运行:一次编译,到处运行(Write Once, Run Anywhere)
  • 内存管理:自动分配和回收内存(垃圾回收)
  • 安全控制:字节码验证、权限管理

类比说明

  • Java 程序 → 一本用中文写的菜谱
  • JVM → 一位精通各国语言的厨师
  • 不同操作系统 → 不同国家的厨房
  • 字节码 → 国际通用的菜谱符号
二、JVM 核心架构

JVM 由三大核心模块组成:

模块功能关键技术
类加载系统加载.class文件到内存双亲委派机制
运行时数据区管理程序运行时的内存分配堆、栈、方法区
执行引擎解释/编译字节码为机器指令解释器、JIT编译器、垃圾回收

三、类加载机制
3.1 类加载流程

类加载分为三个阶段:

  1. 加载(Loading)
    • 查找.class文件
    • 将字节码转换为方法区的数据结构
  2. 链接(Linking)
    • 验证:检查字节码是否符合规范
    • 准备:为静态变量分配内存(默认初始值)
    • 解析:将符号引用转为直接引用
  3. 初始化(Initialization)
    • 执行静态代码块(<clinit>方法)
    • 为静态变量赋真实值

示例

public class Demo {static int value = 10; // 准备阶段 value=0,初始化阶段 value=10static {System.out.println("静态代码块执行");}
}
3.2 双亲委派模型

加载器层级

  1. Bootstrap ClassLoader:加载jre/lib核心库(如java.lang.*)
  2. Extension ClassLoader:加载jre/lib/ext扩展库
  3. Application ClassLoader:加载用户类路径(classpath)
  4. 自定义ClassLoader:用户自定义加载逻辑

工作流程

  1. 子加载器收到加载请求后,先委派父加载器处理
  2. 父加载器无法完成时,子加载器才尝试加载

优势

  • 避免核心类被篡改(如自定义java.lang.String)
  • 保证类全局唯一性
  • public class ClassLoaderDemo {public static void main(String[] args) {// 查看不同类的加载器System.out.println(String.class.getClassLoader()); // null(Bootstrap加载器)System.out.println(ClassLoaderDemo.class.getClassLoader()); // AppClassLoader}
    }
    
    四、运行时数据区
    4.1 内存结构总览
  • +-------------------+
    |   方法区(Method Area)   | ← 存储类信息、常量、静态变量
    +-------------------+
    |   堆(Heap)              | ← 所有对象实例和数组
    +-------------------+
    |   虚拟机栈(VM Stack)     | ← 线程私有的方法调用栈帧
    |   本地方法栈(Native Stack)| ← 调用本地(Native)方法
    |   程序计数器(PC Register) | ← 当前线程执行的字节码行号
    +-------------------+
    
    4.2 堆(Heap)
  • 分代设计
    • 新生代(Young Generation):新创建的对象
      • Eden区(80%)
      • Survivor区(From + To,各10%)
    • 老年代(Old Generation):长期存活的对象
    • 元空间(Metaspace,JDK8+):类元数据(替代永久代)
  • 对象分配流程

  • 新对象优先分配到Eden区
  • Eden满时触发Minor GC
  • 存活对象复制到Survivor区(年龄+1)
  • 年龄达到阈值(默认15)后进入老年代

示例代码

public class HeapDemo {public static void main(String[] args) {List<byte[]> list = new ArrayList<>();while (true) {list.add(new byte[1024 * 1024]); // 持续创建1MB数组,触发OOM}}
}
// 输出:java.lang.OutOfMemoryError: Java heap space
4.3 虚拟机栈(VM Stack)
  • 栈帧结构
    • 局部变量表(Local Variables)
    • 操作数栈(Operand Stack)
    • 动态链接(Dynamic Linking)
    • 方法返回地址(Return Address)
  • 栈溢出示例
  • public class StackOverflowDemo {static void recursiveCall() {recursiveCall(); // 无限递归}public static void main(String[] args) {recursiveCall();}
    }
    // 输出:java.lang.StackOverflowError
    
    4.4 方法区(Method Area)
  • 存储内容
    • 类结构信息(字段、方法、构造函数)
    • 运行时常量池
    • JIT编译后的代码缓存
  • 元空间溢出示例

  • public class MetaspaceOOM {static class OOMObject {}public static void main(String[] args) {// 使用CGLIB动态生成类Enhancer enhancer = new Enhancer();enhancer.setSuperclass(OOMObject.class);enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> proxy.invokeSuper(obj, args1));while (true) {enhancer.create(); // 持续生成代理类}}
    }
    // 输出:java.lang.OutOfMemoryError: Metaspace
    
    五、垃圾回收(GC)
    5.1 判断对象可回收
  • 引用计数法:循环引用问题(已弃用)
  • 可达性分析:从GC Roots出发,不可达的对象可回收
    • GC Roots包括:
      • 虚拟机栈中引用的对象
      • 方法区中静态属性引用的对象
      • 本地方法栈中JNI引用的对象
  • 示例
  • public class GCRootsDemo {Object instance;public static void main(String[] args) {GCRootsDemo a = new GCRootsDemo();GCRootsDemo b = new GCRootsDemo();a.instance = b;b.instance = a;a = null;b = null; // 此时两个对象仍互相引用,但不可达,会被回收System.gc();}
    }
    
    5.2 垃圾回收算法
    算法原理适用场景
    标记-清除标记可回收对象后清除老年代(CMS)
    复制将存活对象复制到新空间新生代(Serial、ParNew)
    标记-整理标记后整理内存空间老年代(Serial Old)
    分代收集根据对象年龄采用不同算法现代JVM默认方案

复制算法示意图

新生代内存布局:
+-----------+------------+-----------+
|   Eden    | From(S0)   | To(S1)    |
+-----------+------------+-----------+
Minor GC后存活对象复制到To区,清空Eden和From
5.3 垃圾收集器
收集器特点适用场景
Serial单线程,Stop-The-World客户端模式
ParNewSerial的多线程版本新生代(配合CMS)
CMS并发标记清除,低停顿老年代
G1分区收集,可预测停顿时间JDK9+默认
ZGC低延迟(<10ms),大堆内存超大内存应用

G1收集器示例配置

java -XX:+UseG1GC -Xmx4g -XX:MaxGCPauseMillis=200 MyApp
六、执行引擎
6.1 解释执行
  • 逐行解释字节码:效率低,但启动快
  • 示例javap -c MyClass.class 查看字节码
6.2 JIT编译(Just-In-Time)
  • 热点代码检测:统计方法调用次数
  • 编译优化技术
    • 方法内联(Method Inlining)
    • 逃逸分析(Escape Analysis)
    • 循环展开(Loop Unrolling)

逃逸分析示例

public class EscapeAnalysisDemo {public static void main(String[] args) {for (int i = 0; i < 1000000; i++) {createObject();}}static void createObject() {Object obj = new Object(); // 对象未逃逸,可能被栈上分配}
}
6.3 分层编译(Tiered Compilation)
  • 编译级别
    • 0:解释执行
    • 1:简单快速编译(C1)
    • 2:完全优化编译(C2)
  • 参数控制-XX:TieredStopAtLevel=3

七、性能监控与调优
7.1 常用工具
工具功能示例命令
jps查看Java进程IDjps -l
jstat监控GC情况jstat -gcutil <pid> 1000
jmap生成堆转储快照jmap -dump:format=b,file=heap.bin <pid>
VisualVM图形化性能分析监控CPU、内存、线程

jstat输出示例

S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
0.00 100.00  25.43  68.50  95.12  91.03     10    0.123     2    0.456    0.579
7.2 常见JVM参数
参数作用示例值
-Xms / -Xmx初始/最大堆内存-Xms512m -Xmx4g
-XX:NewRatio新生代与老年代比例-XX:NewRatio=3(新生代占1/4)
-XX:SurvivorRatioEden与Surviv区比例-XX:SurvivorRatio=8(Eden:S0:S1=8:1:1)
-XX:+PrintGCDetails打印详细GC日志

八、实战案例
8.1 内存泄漏排查

步骤

  1. 使用jps获取进程ID
  2. jmap -dump:format=b,file=heap.bin <pid> 导出堆快照
  3. 用MAT(Memory Analyzer Tool)分析
  4. 查找支配树中的大对象

常见原因

  • 静态集合类持有对象引用
  • 未关闭的数据库连接
  • 监听器未注销
8.2 GC优化案例

问题现象:Full GC频繁,每次耗时2秒
分析步骤

  1. jstat -gcutil <pid> 1000 发现老年代快速填满
  2. jmap -histo <pid> 发现大量相同类实例
  3. 检查代码发现缓存未设置上限
    解决方案:改用LRU缓存,限制最大条目数

九、JVM发展前沿
9.1 GraalVM
  • 多语言支持:Java、JavaScript、Python等
  • 原生镜像(Native Image):提前编译为本地可执行文件
  • 示例native-image -jar myapp.jar
9.2 Project Loom
  • 虚拟线程(Virtual Threads):轻量级线程,支持百万级并发
  • 示例
  • Thread.startVirtualThread(() -> {System.out.println("Hello from virtual thread!");
    });
    
    9.3 ZGC与Shenandoah
  • 亚毫秒级停顿:适用于金融交易系统
  • 配置示例
  • java -XX:+UseZGC -Xmx16g -XX:+UseLargePages MyApp
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/82407.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV CUDA 模块图像过滤-----创建一个计算图像导数的滤波器函数createDerivFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::createDerivFilter 是 OpenCV CUDA 模块中的一个工厂函数&#xff0c;用于创建一个计算图像导数的滤波器。这个滤波器可以用来计算图像…

Spring Boot 接口开发实战指南

Spring Boot 接口开发实战指南 一、基础接口开发步骤 1.1 添加必要依赖 <!-- pom.xml --> <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></depen…

题目 3325: 蓝桥杯2025年第十六届省赛真题-2025 图形

题目 3325: 蓝桥杯2025年第十六届省赛真题-2025 图形 时间限制: 2s 内存限制: 192MB 提交: 494 解决: 206 题目描述 小蓝要画一个 2025 图形。图形的形状为一个 h w 的矩形&#xff0c;其中 h 表示图形的高&#xff0c;w 表示图形的宽。当 h 5,w 10 时&#xff0c;图形如下所…

UML 时序图 使用案例

UML 时序图 UML 时序图 (Sequence Diagram)时序图的主要元素消息类型详解时序图示例时序图绘制步骤时序图的应用场景 UML 时序图 (Sequence Diagram) 时序图是UML(统一建模语言)中用于展示对象之间交互行为的动态视图&#xff0c;它特别强调消息的时间顺序。 时序图的主要元素…

PPT连同备注页(演讲者模式)一块转为PDF

首先&#xff0c;进入创建PDF/XPS&#xff1a; 然后进入选项&#xff1a; 发布选项-发布内容里选备注页&#xff1a; 导出的原始结果是这样的&#xff1a; 这个时候裁剪一下&#xff0c;范围为所有页面&#xff1a; 最终结果&#xff1a; 如果导出不选“备注页”而是只勾选“包…

AI时代新词-多模态(Multimodal)

一、什么是多模态&#xff08;Multimodal&#xff09;&#xff1f; 多模态&#xff08;Multimodal&#xff09;是指在人工智能中&#xff0c;融合多种不同类型的信息&#xff08;如文本、图像、语音、视频等&#xff09;进行处理和分析的技术。与传统的单一模态&#xff08;例…

【图像大模型】Stable Diffusion XL:下一代文本到图像生成模型的技术突破与实践指南

Stable Diffusion XL&#xff1a;下一代文本到图像生成模型的技术突破与实践指南 一、架构设计与技术演进1.1 核心架构革新1.2 关键技术突破1.2.1 双文本编码器融合1.2.2 动态扩散调度 二、系统架构解析2.1 完整生成流程2.2 性能指标对比 三、实战部署指南3.1 环境配置3.2 基础…

图像分割技术的实现与比较分析

引言 图像分割是计算机视觉领域中的一项基础技术&#xff0c;其目标是将数字图像划分为多个图像子区域&#xff08;像素的集合&#xff09;&#xff0c;以简化图像表示&#xff0c;便于后续分析和理解。在医学影像、遥感图像分析、自动驾驶、工业检测等众多领域&#xff0c;图…

摩尔线程S4000国产信创计算卡性能实战——Pytorch转译,多卡P2P通信与MUSA编程

简介 MTT S4000 是基于摩尔线程曲院 GPU 架构打造的全功能元计算卡&#xff0c;为千亿规模大语言模型的训练、微调和推理进行了定制优化&#xff0c;结合先进的图形渲染能力、视频编解码能力和超高清 8K HDR 显示能力&#xff0c;助力人工智能、图形渲染、多媒体、科学计算与物…

「从0到1」构建工业物联网监控系统:ARM+Quarkus+Prometheus技术栈全记录

在工业4.0浪潮中&#xff0c;边缘计算正成为智能制造的核心基础设施。ARM架构边缘计算机凭借其低功耗、高能效比和模块化设计优势&#xff0c;正在重塑工业物联网&#xff08;IIoT&#xff09;的监控体系。当Java的跨平台能力与Prometheus的实时监控体系相结合&#xff0c;为工…

【HW系列】—web常规漏洞(文件上传漏洞)

文章目录 一、简介二、危害三、文件检测方式分类四、判断文件检测方式五、文件上传绕过技术六、漏洞防御措施 一、简介 文件上传漏洞是指Web应用程序在处理用户上传文件时&#xff0c;未对文件类型、内容、路径等进行严格校验和限制&#xff0c;导致攻击者可上传恶意文件&…

如何设计ES的冷热数据分离架构?Elasticsearch 集群如何实现高可用?如何避免脑裂问题?如果出现脑裂如何恢复?

以下为Elasticsearch架构设计与高可用方案详细说明&#xff1a; 冷热架构 一、冷热数据分离架构设计&#xff08;文字描述模拟架构图&#xff09; [Hot Layer] │ ├─ SSD节点组&#xff08;3节点&#xff09; │ ├─ 角色&#xff1a;ingest/data/hot │ ├─ 存…

Trivy 镜像漏洞扫描:从零入门到实战指南

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 ——手把手带你掌握容器安全核心工具 一、安装配置&#xff1a;三步完成 Trivy 部署 Trivy 是由 Aqua Security 开发的开源容器安全工具&#xff0c;支持…

SQL基础概念以及SQL的执行方式

1. SQL入门 1.1. SQL语言功能 可以把 SQL 语言按照功能划分成以下的 4 个部分&#xff1a; DDL&#xff0c;英文叫做 Data Definition Language&#xff0c;也就是数据定义语言&#xff0c;它用来定义我们的数据库对象&#xff0c;包括数据库、数据表和列。通过使用 DDL&…

Rust 1.0 发布十周年,梦想再度扬帆起航!

目录 引言&#xff1a;发布十周年&#xff0c;锋芒露今朝 一、Rust的诞生&#xff1a;源于安全的初心 二、Rust 1.0&#xff1a;十年耕耘&#xff0c;硕果累累 三、核心利器&#xff1a;安全、并发与性能的十年锤炼 四、生态与应用&#xff1a;十年拓展&#xff0c;遍地开…

x86 与 ARM 汇编深度对比:聚焦 x86 汇编的独特魅力

一、引言 汇编语言是硬件与软件的桥梁&#xff0c;x86 和 ARM 作为两大主流架构&#xff0c;其汇编语言在设计理念、指令集、编程风格上差异显著。本文以 x86 汇编为核心&#xff0c;结合与 ARM 的对比&#xff0c;解析 x86 汇编的技术细节与应用场景&#xff0c;助力开发者深…

入驻面包多了

前言 入驻面包多了&#xff0c;其实已经开通面包多账号老久了&#xff0c;一直没有认证&#xff0c;因为没什么拿得出手的作品。 后边会努力沉淀&#xff0c;希望能出一些作品&#xff0c;给大家带来一些帮助&#xff0c;然后能赚到一些些奶茶钱。 一个小工具 上架了一个Win…

Python----目标检测(MS COCO数据集)

一、MS COCO数据集 COCO 是一个大规模的对象检测、分割和图像描述数据集。COCO有几个 特点&#xff1a; Object segmentation&#xff1a;目标级的分割&#xff08;实例分割&#xff09; Recognition in context&#xff1a;上下文中的识别&#xff08;图像情景识别&#xff0…

【Spring AI集成实战】基于NVIDIA LLM API构建智能聊天应用:从配置到函数调用全解析

【Spring AI集成实战】基于NVIDIA LLM API构建智能聊天应用&#xff1a;从配置到函数调用全解析 前言 在人工智能应用开发领域&#xff0c;大语言模型&#xff08;LLM&#xff09;的集成能力至关重要。NVIDIA作为全球领先的GPU厂商&#xff0c;其LLM API提供了对Meta Llama-3.…

通用的管理账号设置设计(一)

背景 首先说明一下需求背景&#xff1a; 在整个角色分类中分为管理员和用户&#xff0c;用户可以分为很多级别&#xff0c;比如用户处于哪个组&#xff08;group&#xff09;&#xff0c;用户处于哪个site&#xff08;城市&#xff09;。管理员可以&#xff1a; 2.1 锁定整个…