什么是JVM类数据共享(CDS)?
JVM类数据共享 (Class Data Sharing, CDS)是一种 优化JVM启动速度和内存使用 的技术。它通过 在多个Java进程之间共享类元数据,避免每个进程重复加载和解析相同的类,进而提升启动速度并节省内存。
可以简单理解为:在一个大家都需要读取的文件中,JVM通过预先解析类信息,存储为一个共享的类数据文件,当多个Java进程需要时,可以从这个共享文件中读取,而不是每次都重新加载。
JVM类数据共享的原理
- 类元数据 :JVM在加载Java类时,需要解析
.class
文件并生成类的元数据(如类名、方法、字段等)。这些数据保存在内存中。 - 共享机制 :CDS通过预先将这些元数据保存到一个 共享类归档文件 中(通常是
classes.jsa
文件),并允许后续的JVM进程直接从该文件中加载类元数据,而无需再次解析和加载类文件。 - 减少内存占用:多个JVM实例可以共享这部分内存,避免重复加载相同的类数据。
- 加速启动:因为类数据是从共享归档文件中直接读取的,所以跳过了大部分的类解析过程,显著提升了JVM启动速度。
JVM类数据共享的历史
- JDK 1.5(2004年) 首次引入了 CDS(Class Data Sharing),最初只是针对JVM自身类库进行优化。
- JDK 10 推出了 AppCDS(应用类数据共享),允许用户类数据也能够被共享。
- JDK 12 引入了 动态CDS归档,简化了CDS的使用流程,使其可以动态生成共享的类归档文件。
JVM类数据共享的目的
- 加快JVM启动时间:对于需要大量类加载的应用(如 Spring Boot),CDS可以跳过重复的类加载和解析过程,显著减少启动时间。
- 减少内存使用:多个JVM实例可以共享同一份类数据,节省了内存使用。
- 提高系统资源利用率:尤其是在多实例部署(如微服务架构)或容器化场景下,CDS优化了资源分配,避免重复加载相同的类数据。
JVM类数据共享的使用场景
- 微服务环境:在一个服务器上同时运行多个相似的微服务时,这些服务通常会使用相同的依赖和库。CDS通过共享类数据,减少了内存消耗。
- 容器化部署:如在Docker或Kubernetes中,CDS可以减少每个Java容器的内存占用并加快启动速度。
- 大规模集群部署:当在大规模集群上运行大量Java进程时,CDS通过共享类数据优化了系统性能和资源分配。
Spring Boot中的CDS启用情况
-
Spring Boot 2.x 版本 :CDS默认没有启用,需要手动设置JVM参数来启动CDS。例如:
bashjava -Xshare:on -XX:SharedArchiveFile=classes.jsa -jar myapp.jar
-
Spring Boot 3.x 版本及更高:在JDK 11及以上版本中,Spring Boot应用开始更多利用JDK的CDS机制,尤其是在容器化部署中会默认启用。
通过CDS,Spring Boot应用可以显著加快启动速度,尤其是对于依赖大量类库的微服务架构和云原生环境。
启用和禁用CDS的控制
-
启用CDS:默认情况下可以通过以下命令启用CDS:
bashjava -Xshare:on -XX:SharedArchiveFile=classes.jsa -jar myapp.jar
-
禁用CDS的常见方法:
-
-Xshare:off:完全禁用CDS。
-
-XX:-UseSharedSpaces :这是另一种禁用CDS的方式,它完全禁用类数据共享机制。
bashjava -XX:-UseSharedSpaces -jar myapp.jar
-
-
-XX:SharedArchiveFile 和 -XX:-UseSharedSpaces 的区别:
-
-XX:SharedArchiveFile=<path>
:指定类数据共享的归档文件路径。可以自定义一个路径来存储类元数据,例如:bashjava -XX:SharedArchiveFile=/path/to/myclasses.jsa -jar myapp.jar
这意味着共享类数据将存储在自定义的
.jsa
文件中,多个Java进程可以共享该数据。 -
-XX:-UseSharedSpaces
:完全禁用类数据共享,不仅是系统类的数据共享,也包括应用类的数据共享。这种方式直接禁用了CDS的机制,不再从任何共享文件中加载类数据。
-
特殊情况下的禁用
在一些JDK 17及更新的版本中,某些JVM选项(如 -Xshare:none
)可能不再受支持。这是因为在这些版本中,JVM对CDS的集成更深,部分功能不允许完全禁用。遇到这种情况时,你可以使用 -XX:-UseSharedSpaces
来禁用类数据共享,或者使用 -XX:SharedArchiveFile=NONE
来仅禁用应用类数据共享。
CDS在实际中的配置示例
假设你有一个 Spring Boot 项目,并且你使用了 JDK 11,你可以通过以下命令来启用CDS:
bash
java -Xshare:on -XX:SharedArchiveFile=classes.jsa -jar my-springboot-app.jar
第一次运行时,JVM会生成共享类数据并保存到 classes.jsa
中。下次启动时,JVM会直接从该文件读取类数据,跳过类解析过程,进而加快启动速度。
总结
- JVM类数据共享(CDS) 是JVM的一项优化技术,旨在加快启动时间和减少内存使用。它通过共享类数据,避免重复解析和加载类数据。
- CDS 从 JDK 1.5 开始引入,经过多次迭代改进,JDK 10 引入了 AppCDS ,进一步允许用户类共享,JDK 12 引入了动态CDS,简化了配置和使用流程。
- 在Spring Boot应用中,特别是在 JDK 11及以上版本 中,CDS的作用尤为明显,特别适用于云原生和容器化环境。
- 禁用CDS 可以使用
-Xshare:off
或-XX:-UseSharedSpaces
,后者可以完全关闭类数据共享机制。 - 在某些JDK 17版本中,
-Xshare:none
可能不被支持,此时可以使用-XX:-UseSharedSpaces
来禁用CDS。