Java类共享加速JVM启动方法解析
本篇文章给大家分享《Java类共享技术如何提升JVM启动速度》,覆盖了文章的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握它。
CDS/AppCDS的核心原理是将JVM启动时所需的类预先处理并存储为共享文件,后续启动时直接加载以节省时间。其通过减少类加载、解析和验证过程显著提升启动速度,尤其适用于微服务等快速启动场景。实际提速效果因应用而异,通常几十到几百毫秒不等,大型应用甚至可达秒级优化。配置流程包括:1.运行应用生成类列表;2.基于列表创建.jsa共享文件;3.启动时指定使用该文件。常见问题有归档失效、动态加载类未包含、内存映射限制、调试复杂化及非万能适用性。除加速启动外,AppCDS还可降低内存占用、减少JIT编译量并加快应用预热,但存在维护成本高、平台依赖性强及难以覆盖所有类等局限性。

Java类数据共享技术,简单来说,就是通过预先将JVM启动时需要加载的核心类(以及应用程序类,如果配置了的话)打包成一个共享存档文件,然后在后续的JVM实例启动时直接映射这个文件到内存,从而显著减少类加载、解析和验证的时间,大幅度加速JVM的启动过程。这就像是把常用的工具预先摆好,而不是每次用都得从箱子里找一遍,自然就快多了。

解决方案
要真正理解并利用Java类数据共享(Class Data Sharing, CDS,以及更进一步的Application Class Data Sharing, AppCDS)来加速JVM启动,核心在于创建一个包含所需类定义的共享存档。这个过程通常分两步:首先,让JVM运行一次,收集所有加载的类信息并生成一个类列表;其次,利用这个列表,将这些类的数据“倾倒”到一个共享文件中。后续的JVM实例在启动时,就可以直接加载并使用这个预编译、预验证的类数据,省去了大量的磁盘I/O、字节码解析和即时编译(JIT)的初始工作。这对于那些需要快速启动的微服务、无服务器函数或者命令行工具来说,简直是福音。

CDS/AppCDS的核心原理是什么?它真的能省多少时间?
CDS和AppCDS的原理,其实挺直观的。你想啊,每次JVM启动,它都得把一大堆JDK自带的类(比如java.lang.Object、String这些)从JAR包里读出来,然后解析字节码,做安全验证,再把这些类的元数据放到内存里。这个过程,虽然看起来很快,但对于成千上万个类来说,累积起来的时间消耗可不小。CDS做的,就是把这些“固定不变”的类,在第一次启动时就处理好,然后把它们序列化到一个 .jsa(Java Shared Archive)文件里。后续的JVM,就直接把这个 .jsa 文件映射到自己的进程内存空间,省去了重复解析和验证的步骤。
至于能省多少时间,这个嘛,没有一个固定答案,得看你的应用有多大、类库有多复杂。但通常来说,几十到几百毫秒的提升是常态,对于一些大型的、类加载非常多的应用,甚至能看到秒级的加速。我之前有个项目,一个基于Spring Boot的微服务,启动时间从七八秒优化到四五秒,其中AppCDS就贡献了不少。这玩意儿最明显的效果,就是体现在“冷启动”上,也就是JVM第一次启动或者重启的时候。当你的服务需要快速扩容或者频繁部署时,这个优势就非常突出了。它不仅仅是启动快那么简单,因为类元数据是共享的,还能在一定程度上减少内存占用,虽然这通常不是主要目标。

在实际项目中,如何配置和使用AppCDS?有哪些常见的坑?
配置AppCDS,说实话,不复杂,但有些细节你得注意。
基本流程:
生成类列表: 运行你的应用一次,让JVM记录下所有加载的类。
java -Xshare:off -XX:DumpLoadedClassList=my_app_classes.lst -jar your_application.jar
这里
-Xshare:off是为了确保这次运行不使用任何已有的共享归档,纯粹地加载所有类并记录。创建共享归档: 使用上一步生成的类列表,创建
.jsa文件。java -Xshare:dump -XX:SharedClassListFile=my_app_classes.lst -XX:SharedArchiveFile=my_app.jsa -jar your_application.jar
注意,这里的
-jar your_application.jar并不是真的运行应用,而是提供classpath,让JVM知道去哪里找这些类。这一步会把列表中的类数据写入my_app.jsa。使用共享归档: 在后续的应用启动中,指定使用这个归档。
java -Xshare:on -XX:SharedArchiveFile=my_app.jsa -jar your_application.jar
-Xshare:on是开启共享功能。
常见的坑和注意事项:
- 归档失效: 最常见的坑就是归档失效。如果你升级了JDK版本,或者应用的classpath发生了变化(比如增删了依赖,或者依赖的版本变了),那么之前生成的
.jsa文件很可能就不能用了,JVM会报错或者直接忽略它。所以每次应用更新或者JDK升级,你可能都需要重新生成归档。 - 动态加载的类: 如果你的应用大量使用反射、动态代理或者类加载器在运行时动态加载类,那么这些类在生成
my_app_classes.lst的时候可能没有被记录下来。结果就是它们不会被包含在共享归档里,启动时还是得单独加载。所以,生成类列表的那次运行,最好能覆盖到应用的大部分功能路径,尽量让所有核心类都被加载。 - 内存映射:
.jsa文件是内存映射的,这也就意味着它需要磁盘空间,而且在某些严格的容器环境中,可能会遇到权限或者文件系统限制。 - 调试问题: 有时候启用了AppCDS后,如果遇到类加载相关的问题,排查起来可能会稍微复杂一点,因为你得考虑是不是归档的问题。
- 并非万能药: AppCDS主要优化的是类加载阶段。如果你的应用启动慢是因为数据库连接初始化、Spring上下文扫描、大量业务逻辑预热等,那AppCDS的帮助就有限了。它解决的是“基础建设”阶段的效率问题。
除了加速启动,AppCDS还能带来哪些额外的好处?它有局限性吗?
AppCDS除了最直接的启动加速,确实还有一些“附带”的好处,但它也绝非完美无缺。
额外的好处:
- 内存占用优化: 由于共享归档中的类元数据可以被多个JVM实例共享,这意味着在同一台服务器上运行多个相同的Java应用实例时,这些实例可以共享同一份类数据在内存中,从而减少整体的内存占用。这对于部署高密度微服务集群的场景尤其有价值。
- JIT编译减少: 虽然AppCDS主要优化的是类加载,但它也间接减少了启动初期JIT编译器的工作量。因为共享归档中的类在生成时已经被处理过,JVM在启动时可以直接使用这些预处理好的数据,减少了对字节码的解析和一些初步的优化工作,从而让JIT编译器可以更快地投入到应用热点代码的优化中。
- 更快的应用“预热”: 理论上讲,由于核心类已经加载并处理完毕,应用启动后可以更快地达到其峰值性能,因为JVM不需要在运行时再花费大量时间去加载和处理这些基础类。
局限性:
- 维护成本: 最大的局限性我觉得就是维护成本。每次JDK升级或者应用依赖发生显著变化时,你都得重新生成
.jsa文件。在CI/CD流程中,这需要额外的一个步骤来自动化。如果忘记更新,轻则AppCDS失效,重则应用启动失败。 - 不解决所有启动问题: 就像前面提到的,AppCDS只针对类加载阶段。如果你的应用启动慢是因为Spring Bean初始化耗时、数据库连接池预热、或者其他业务逻辑上的复杂性,AppCDS对此无能为力。它不是一个能解决所有启动性能问题的银弹。
- 平台依赖性: 生成的
.jsa文件通常是平台相关的,比如你在Linux上生成的,不能直接拿到Windows上去用。而且,它也和具体的JDK版本绑定,跨版本使用通常会失败。 - 复杂应用的类列表生成: 对于一些非常复杂的应用,特别是那些大量使用插件、模块化加载或者动态生成类的应用,要生成一个“完整且准确”的类列表可能会比较困难,导致部分类无法被共享。
总的来说,AppCDS是一个非常实用的JVM优化技术,尤其适合那些对启动速度有严格要求的场景。但它也要求你在部署和维护流程中加入额外的考量,不能指望它一劳永逸地解决所有性能问题。
到这里,我们也就讲完了《Java类共享加速JVM启动方法解析》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于类加载,AppCDS,JVM启动,共享存档的知识点!
Golang微服务优化技巧全解析
- 上一篇
- Golang微服务优化技巧全解析
- 下一篇
- Python中end参数的作用与用法
-
- 文章 · java教程 | 6小时前 |
- Java栈溢出解决方法及状态分析
- 447浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- Kotlin调用Java方法避免to歧义方法
- 121浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- SpringBatchMaven运行与参数传递教程
- 347浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- 公平锁如何避免线程饥饿问题
- 299浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- Hibernate6.xCUBRID迁移指南
- 226浏览 收藏
-
- 文章 · java教程 | 8小时前 | 代码复用 类型安全 类型参数 extends关键字 Java泛型类
- Java泛型类定义与使用详解
- 480浏览 收藏
-
- 文章 · java教程 | 8小时前 |
- JavaCollectors数据聚合技巧解析
- 161浏览 收藏
-
- 文章 · java教程 | 8小时前 |
- LinkedHashMap删除操作对迭代顺序的影响分析
- 121浏览 收藏
-
- 文章 · java教程 | 9小时前 | java const final immutableobject staticfinal
- final与immutable区别详解
- 201浏览 收藏
-
- 文章 · java教程 | 9小时前 |
- JavaStreamgroupingBy使用教程
- 331浏览 收藏
-
- 文章 · java教程 | 9小时前 |
- JavaXML解析错误处理技巧
- 218浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3166次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3379次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3408次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4512次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3788次使用
-
- 提升Java功能开发效率的有力工具:微服务架构
- 2023-10-06 501浏览
-
- 掌握Java海康SDK二次开发的必备技巧
- 2023-10-01 501浏览
-
- 如何使用java实现桶排序算法
- 2023-10-03 501浏览
-
- Java开发实战经验:如何优化开发逻辑
- 2023-10-31 501浏览
-
- 如何使用Java中的Math.max()方法比较两个数的大小?
- 2023-11-18 501浏览

