什么是CDS?CDS即 Class-Data Sharing,类数据共享功能,该功能可以减少Java应用程序的启动时间和内存占用。

类数据共享功能有助于减少多个Java虚拟机之间的启动时间和内存占用,从JDK12开始,默认的CDS归档文件和JDK二进制文件预先打包,我是用的JDK为OpenJDK OpenJDK 64-Bit Server VM Zulu17.42+19-CA (build 17.0.7+7-LTS, mixed mode, sharing),是支持CDS的。

使用

训练应用程序

  1. 首先初始化一个标准的SpringBoot应用,使用 SpringBoot-3.3.0 + Java17
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── top
│   │   │       └── imyzt
│   │   │           └── learning
│   │   │               └── cds
│   │   │                   └── Java12NewFuturesCdsApplication.java
@SpringBootApplication
public class Java12NewFuturesCdsApplication {
    public static void main(String[] args) {
        SpringApplication.run(Java12NewFuturesCdsApplication.class, args);
    }
}
  1. 将其执行Maven打包成jar文件
➜  mvn package -DskipTests=true
  1. 执行训练命令
➜  cd target
➜  target ✗ java -Djarmode=tools -jar java12-new-futures-cds-0.0.1-SNAPSHOT.jar extract --destination application  
➜  cd application
➜  application ✗ java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar java12-new-futures-cds-0.0.1-SNAPSHOT.jar

训练完成后,application目录下,生成了一系列文件:

➜  application git:(master) ✗ tree
.
├── application.jsa
├── java12-new-futures-cds-0.0.1-SNAPSHOT.jar
└── lib
    ├── jackson-annotations-2.17.1.jar
    ├── jackson-core-2.17.1.jar
    ├── jackson-databind-2.17.1.jar
    ├── jackson-datatype-jdk8-2.17.1.jar
    ├── jackson-datatype-jsr310-2.17.1.jar
    ├── jackson-module-parameter-names-2.17.1.jar
    ├── jakarta.annotation-api-2.1.1.jar
    ├── jul-to-slf4j-2.0.13.jar
    ├── log4j-api-2.23.1.jar
    ├── log4j-to-slf4j-2.23.1.jar
    ├── logback-classic-1.5.6.jar
    ├── logback-core-1.5.6.jar
    ├── micrometer-commons-1.13.0.jar
    ├── micrometer-observation-1.13.0.jar
    ├── slf4j-api-2.0.13.jar
    ├── snakeyaml-2.2.jar
    ├── spring-aop-6.1.8.jar
    ├── spring-beans-6.1.8.jar
    ├── spring-boot-3.3.0.jar
    ├── spring-boot-autoconfigure-3.3.0.jar
    ├── spring-boot-jarmode-tools-3.3.0.jar
    ├── spring-context-6.1.8.jar
    ├── spring-core-6.1.8.jar
    ├── spring-expression-6.1.8.jar
    ├── spring-jcl-6.1.8.jar
    ├── spring-web-6.1.8.jar
    ├── spring-webmvc-6.1.8.jar
    ├── tomcat-embed-core-10.1.24.jar
    ├── tomcat-embed-el-10.1.24.jar
    └── tomcat-embed-websocket-10.1.24.jar
1 directory, 32 files
  1. 使用训练的缓存,在启动应用程序时,补充-XX:SharedArchiveFile参数即可。
➜  application ✗ java -XX:SharedArchiveFile=application.jsa -jar java12-new-futures-cds-0.0.1-SNAPSHOT.jar

启动日志:
Started Java12NewFuturesCdsApplication in 2.262 seconds (process running for 2.805)

对比不使用CDS缓存的启动日志:
Started Java12NewFuturesCdsApplication in 4.464 seconds (process running for 5.341)

可以看出来,尽管只是一个空项目,但是相同配置情况下启动速度都有倍增。

结语

从上面的测试可以看出来,项目的启动速度是有成本的效率增长的,但同时也存在弊端,就是每次应用程序发生变更时,需要冲洗进行jsa文件的训练。

不管是native-jar还是CDS,都是Java在云原生时代解决应用启动过程慢的探索,在应用的自动扩容领域,还是有不少的应用场景。

参考

  1. Spring Boot 3.3.0 新特性| 使用 CDS 优化启动时间
  2. CDS即Class-Data Sharing