深入剖析 JVM:从组成原理到调优实践

news2025/4/2 6:25:53

深入剖析 JVM:从组成原理到调优实践

  • 深入剖析 JVM:从组成原理到调优实践
    • 一、JVM 组成架构:运行 Java 程序的 “幕后引擎”
      • 1.1 内存结构:数据存储的 “分区管理”
      • 1.2 执行引擎:字节码的 “翻译官”
      • 1.3 本地方法接口:连接 Java 与本地代码
    • 二、类加载器:类文件的 “加载枢纽”
      • 2.1 类加载器分类
      • 2.2 双亲委派机制:类加载的 “安全策略”
      • 2.3 类加载过程:加载→验证→准备→解析→初始化
    • 三、垃圾回收:堆内存的 “清理工”
      • 3.1 垃圾对象判断算法
      • 3.2 垃圾回收算法
      • 3.3 垃圾回收器
    • 四、JVM 调优实践:让程序运行更高效
      • 4.1 调优工具
      • 4.2 常见调优场景
      • 4.3 调优案例

深入剖析 JVM:从组成原理到调优实践

一、JVM 组成架构:运行 Java 程序的 “幕后引擎”

JVM(Java Virtual Machine)是 Java 程序运行的基础环境,其核心组成可分为三大模块:内存结构、执行引擎、本地方法接口。
在这里插入图片描述

1.1 内存结构:数据存储的 “分区管理”

在这里插入图片描述

  • 堆(Heap):JVM 中最大的内存区域,用于存储对象实例。几乎所有对象都在堆上分配内存,是垃圾回收的主要区域。根据对象存活周期,又分新生代(Eden 区、Survivor 区)和老年代。

  • 方法区:存储类信息、常量、静态变量等。JDK 8 后,方法区由元空间(Meta Space)实现,使用本地内存,避免了 “永久代” 的内存溢出问题。在这里插入图片描述

  • 虚拟机栈:线程私有,存储方法执行时的栈帧,包括局部变量表、操作数栈、动态链接等。每个方法调用对应一个栈帧入栈,方法执行完毕出栈。在这里插入图片描述

  • 本地方法栈:与虚拟机栈功能类似,用于本地方法(Native 方法)的执行。

  • 程序计数器:记录当前线程执行字节码的位置,是唯一不会出现内存溢出的区域。

1.2 执行引擎:字节码的 “翻译官”

  • 解释器:逐行解释执行字节码,启动速度快,但执行效率低。
  • 即时编译器(JIT):运行时将热点代码(频繁执行的代码)编译为本地机器码,提升执行效率。HotSpot 虚拟机包含 C1(客户端编译器,优化简单代码)和 C2(服务器编译器,深度优化复杂代码)。
  • 垃圾回收器:管理堆内存,回收不再使用的对象,释放内存空间。
    在这里插入图片描述

1.3 本地方法接口:连接 Java 与本地代码

允许 Java 调用本地原生代码(如 C/C++),通过 JNI(Java Native Interface)实现,拓展 Java 对底层系统的操作能力。

二、类加载器:类文件的 “加载枢纽”

在这里插入图片描述

2.1 类加载器分类

  • 启动类加载器(Bootstrap ClassLoader):C++ 实现,加载 Java 核心类库(如 rt.jar 中的 java.lang 包),是最顶层的类加载器。
  • 扩展类加载器(Extension ClassLoader):加载 Java 扩展类库(如 jre/lib/ext 目录下的类),Java 代码实现。
  • 应用类加载器(Application ClassLoader):加载用户自定义类和应用依赖的类库(如项目 classpath 下的类),也是多数 Java 程序的默认类加载器。

2.2 双亲委派机制:类加载的 “安全策略”

  • 工作流程:当类加载器收到类加载请求,先委托父类加载器加载,父类加载器依次向上委托,直到启动类加载器。若父类加载器无法加载,再由当前类加载器加载。
  • 优势:避免类的重复加载,保证 Java 核心类库的安全性。例如,用户自定义的 java.lang.String 不会被加载,始终使用启动类加载器加载的官方版本。

2.3 类加载过程:加载→验证→准备→解析→初始化

  • 加载:通过类全限定名获取二进制字节流,生成类的 Class 对象。
  • 验证:确保字节流符合 JVM 规范,防止恶意代码破坏系统。
  • 准备:为类变量分配内存并设置初始值(如 static int a = 1; 准备阶段 a 初始值为 0)。
  • 解析:将符号引用转为直接引用,优化类之间的访问速度。
  • 初始化:执行类构造器 <clinit>(),初始化类变量和静态代码块。

三、垃圾回收:堆内存的 “清理工”

3.1 垃圾对象判断算法

  • 引用计数法:给对象添加引用计数器,引用增加计数 + 1,减少计数 - 1,计数为 0 则回收。存在循环引用问题,JVM 未采用。
  • 可达性分析算法:以 GC Roots(如虚拟机栈变量、静态变量等)为起点,通过引用链标记存活对象,未标记的对象可回收,是 JVM 主流算法。

3.2 垃圾回收算法

  • 标记 - 清除算法:先标记可回收对象,再统一清除。存在内存碎片问题。
  • 标记 - 整理算法:标记后,将存活对象向一端移动,清除端边界外内存,解决碎片问题,但耗时较长。
  • 复制算法:将内存分为两块,存活对象复制到另一块,清除原块。适合新生代,因新生代对象存活率低。
  • 分代收集算法:结合不同区域特点,新生代用复制算法,老年代用标记 - 清除或标记 - 整理算法。

3.3 垃圾回收器

  • Serial 收集器:单线程收集器,简单高效,适合客户端应用。
  • ParNew 收集器:Serial 多线程版本,常与 CMS 收集器配合。
  • Parallel Scavenge 收集器:关注吞吐量,适合后台计算任务。
  • CMS 收集器:以获取最短回收停顿时间为目标,采用标记 - 清除算法,可能产生碎片。
  • G1 收集器:将堆划分为多个区域,跟踪区域垃圾价值,优先回收价值高的区域,适合大内存、低延迟场景。

四、JVM 调优实践:让程序运行更高效

在这里插入图片描述

4.1 调优工具

  • JConsole:图形化工具,监控堆内存使用、线程状态等。
  • JVisualVM:功能更强大,支持生成堆转储快照、分析内存泄漏。
  • GC 日志分析:通过 -XX:+PrintGCDetails 打印 GC 日志,分析 GC 频率、耗时,调整堆参数。

4.2 常见调优场景

  • 内存溢出(OOM):通过分析堆转储文件,定位大对象或内存泄漏代码。调整堆大小(如 -Xmx-Xms)。
  • GC 频繁:若新生代 GC 频繁,可调整新生代与老年代比例(如 -XX:NewRatio);若老年代 GC 频繁,检查大对象分配是否合理。
  • 性能优化:针对热点代码,调整 JIT 编译参数(如 -XX:CompileThreshold),提升编译效率。

4.3 调优案例

某电商应用频繁出现 Full GC,通过分析 GC 日志发现老年代内存增长快。检查代码发现,缓存未设置过期时间,导致对象长期占用老年代。优化缓存策略,添加过期机制,同时调整堆参数 -Xmx4g -Xms4g -XX:MaxTenuringThreshold=15,降低 Full GC 频率,系统响应时间显著缩短。

JVM 作为 Java 程序的核心运行环境,深入理解其组成、类加载机制、垃圾回收原理及调优方法,能帮助开发者更好地优化程序性能,解决运行时问题,打造高效稳定的 Java 应用。

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

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

相关文章

阿里云下一代可观测时序引擎-MetricStore 2.0

作者&#xff1a;徐昊&#xff08;博澍&#xff09; 背景 作为可观测场景使用频度最高的数据类型&#xff0c;Metrics 时序数据在可观测领域一直占有着重要地位&#xff0c;无论是从全局视角来观测系统整体状态&#xff0c;还是从大范围数据中定位某一个异常的位置&#xff0…

从入门到精通【 MySQL】 数据库约束与设计

文章目录 &#x1f4d5;1. 数据库约束✏️1.1 NOT NULL 非空约束✏️1.2 DEFAULT 默认值约束✏️1.3 UNIQUE 唯一约束✏️1.4 PRIMARY KEY 主键约束✏️1.5 FOREIGN KEY 外键约束✏️1.6 CHECK 约束 &#x1f4d5;2. 数据库设计✏️2.1 第一范式✏️2.2 第二范式✏️2.3 第三范…

Dubbo 通信流程 - 服务的调用

Dubbo 客户端的使用 在 Dubbo 应用中&#xff0c;往类成员注解 DubboReference&#xff0c;服务启动后便可以调用到远端&#xff1a; Component public class InvokeDemoFacade {AutowiredDubboReferenceprivate DemoFacade demoFacade;public String hello(String name){// …

【数据结构】哈夫曼树

哈夫曼树 在学习哈夫曼树之前&#xff0c;先了解以下几个概念&#xff1a; 一&#xff1a;**路径长度&#xff1a;**在一棵树中&#xff0c;从一个节点到另一个节点所经过的“边”的数量&#xff0c;被我们称为两个节点之间的路径长度。 二&#xff1a;**树的路径长度&#xf…

HCIP(TCP)(2)

1. TCP三次握手 SYN (同步序列编号) 报文: 客户端发送 SYN 报文&#xff0c;开始建立连接&#xff0c;并初始化序列号。 SYN-ACK (同步序列编号-确认) 报文: 服务器收到 SYN 报文后&#xff0c;回复 SYN-ACK 报文&#xff0c;确认连接请求&#xff0c;并初始化自己的序列号和确…

基于Web的交互式智能成绩管理系统设计

目录 摘要 绪论 一、应用背景 二、行业发展现状 三、程序开发的重要意义 四、结语 1 代码 2 数据初始化模块 3 界面布局模块 4 核心功能模块 5 可视化子系统 6 扩展功能模块 7 架构设计亮点 功能总结 一、核心数据管理 二、智能分析体系 三、可视化系统 四、扩…

k8s日志管理

k8s日志管理 k8s查看日志查看集群中不是完全运行状态的pod查看deployment日志查看service日志进入pod的容器内查看日志 管理k8s组件日志kubectl logs查看日志原理 管理k8s应用日志收集k8s日志思路收集标准输出收集容器中日志文件 k8s查看节点状态失败k8s部署prometheus监控 k8s…

element-plus中,Loading 加载组件的使用

一.基本使用 给一个组件&#xff0c;如&#xff1a;table表格&#xff0c;加上v-loading"true"即可。 举例&#xff1a;复制如下代码。 <template><el-table v-loading"loading" :data"tableData" style"width: 100%"><…

Mybatis_Plus中的常用注解

目录 1、TableName TableId TableId的type属性 TableField 1、TableName 经过以上的测试&#xff0c;在使用MyBatis-Plus实现基本的CRUD时&#xff0c;我们并没有指定要操作的表&#xff0c;只是在 Mapper接口继承BaseMapper时&#xff0c;设置了泛型User&#xff0c;而操…

高并发金融系统,“可观测-可追溯-可回滚“的闭环审计体系

一句话总结 在高并发金融系统中&#xff0c;审计方案设计需平衡"观测粒度"与"系统损耗"&#xff0c;通过双AOP实现非侵入式采集&#xff0c;三表机制保障操作原子性&#xff0c;最终形成"可观测-可追溯-可回滚"的闭环体系。 业务痛点与需求 在…

企业内训|DeepSeek技术革命、算力范式重构与场景落地洞察-某头部券商

3月19日北京&#xff0c;TsingtaoAI公司负责人汶生受邀为某证券公司管理层和投资者举办专题培训&#xff0c;围绕《DeepSeek技术革命、算力范式重构与场景落地洞察》主题&#xff0c;系统阐述了当前AI技术演进的核心趋势、算力需求的结构性变革&#xff0c;以及行业应用落地的关…

VS Code C/C++项目设置launch.json中的environment参数解决支持库路径问题

问题描述 Windows 11 VS Code C/C 开发环境搭建分别写了c和cpp两个示例代码&#xff0c;在运行过程中c代码没有发现问题&#xff08;可能简单&#xff0c;没有用到太多支持&#xff09;&#xff0c;但使用了stl的cpp代码并没有运行出来&#xff0c;如下图&#xff1a; 出问题…

怎样解决 Windows 11 上的 DirectX 错误,最新DX 问题解决方法

在使用 Windows 11 操作系统的过程中&#xff0c;大家可能会遇到 DirectX 错误的情况&#xff0c;这可能会给游戏体验、多媒体应用甚至是系统的整体性能带来负面影响。不过别担心&#xff0c;本文将为大家详细介绍如何解决 Windows 11 上的 DirectX 错误&#xff0c;让您的系统…

PH热榜 | 2025-03-30

1. Deepcord 标语&#xff1a;Discord 数据分析&#xff1a;获取指标洞察与受众研究 介绍&#xff1a;Deepcord&#xff1a;为社区建设者提供的Discord分析工具。跟踪超过50万个服务器的指标&#xff0c;发现热门社区&#xff0c;监控竞争对手&#xff0c;找到你的目标受众。…

Open webui的使用

问题 之前本地量化模型管理器ollama的文章&#xff0c;我们知道可以通过ollama来管理本地量化模型&#xff0c;也能够在命令行中与相关模型进行对话。现在我们想要在有个web页面通过浏览器来与本地模型对话。这里我们就使用Open webui作为界面来与本地模型对话。 安装启动 这…

STM32单片机的桌面宠物机器人(基于HAL库)

效果 基于STM32单片机的桌面宠物机器人 概要 语音模块&#xff1a;ASR PRO&#xff0c;通过天问block软件烧录语音指令 主控芯片&#xff1a;STM32F103C8T6 使用HAL库 屏幕&#xff1a;0.96寸OLED屏&#xff0c;用来显示表情 4个舵机&#xff0c;用来当作四只腿 底部一个面…

Ubuntu 22 Linux上部署DeepSeek R1保姆式操作详解(ollama方式)

操作系统&#xff1a;Ubuntu Linux 22.04 一、安装模型运行环境 打开链接https://ollama.com/download/linux 1.安装ollama &#xff08;1&#xff09;一条指令即可实现的简易版安装方法&#xff08;也可称为在线安装&#xff09; curl -fsSL https://ollama.com/install.s…

深度学习处理时间序列(6)

RNN的高级用法 循环dropout&#xff08;recurrent dropout&#xff09;​&#xff1a;这是dropout的一种变体&#xff0c;用于在循环层中降低过拟合。 循环层堆叠&#xff08;stacking recurrent layers&#xff09;​&#xff1a;这会提高模型的表示能力&#xff08;代价是更…