JVM AOT 缓存

预编译(AOT)缓存是 Java 24 中通过 JEP 483 引入的一项 JVM 功能,可以帮助缩短 Java 应用程序的启动时间和减少内存占用。AOT 缓存是 类数据共享 (CDS) 的自然演进。Spring Framework 支持 CDS 和 AOT 缓存,建议您在所使用的 JVM 版本(Java 24+)中优先使用后者。 要使用此功能,需要为应用程序的特定类路径创建 AOT 缓存。可以在已部署的实例上创建此缓存,或者在训练运行期间(例如在打包应用程序时)创建,这得益于 Spring Framework 提供的钩子点,可简化此类用例。一旦缓存可用,用户应通过 JVM 标志选择使用它。

如果您正在使用 Spring Boot,强烈建议利用其 可执行 JAR 解包支持, 该支持旨在满足 AOT 缓存和 CDS 的类加载要求。

创建缓存

AOT 缓存通常可以在应用程序退出时创建。Spring Framework 提供了一种操作模式,在该模式下,一旦 ApplicationContext 刷新,进程就可以自动退出。在此模式下,所有非延迟初始化的单例都已实例化,并且 InitializingBean#afterPropertiesSet 回调已调用;但生命周期尚未开始,并且 ContextRefreshedEvent 尚未发布。

要在训练运行期间创建缓存,可以指定 -Dspring.context.exit=onRefresh JVM 标志来启动您的 Spring 应用程序,并在 ApplicationContext 刷新后退出:

  • AOT 缓存

  • CDS

# Both commands need to be run with the same classpath
java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -Dspring.context.exit=onRefresh ...
java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot ...
# To create a CDS archive, your JDK/JRE must have a base image
java -XX:ArchiveClassesAtExit=app.jsa -Dspring.context.exit=onRefresh ...

使用缓存

缓存文件创建后,您可以使用它来更快地启动应用程序:

  • AOT 缓存

  • CDS

# With the same classpath (or a superset) tan the training run
java -XX:AOTCache=app.aot ...
# With the same classpath (or a superset) tan the training run
java -XX:SharedArchiveFile=app.jsa ...

请注意日志和启动时间,以检查 AOT 缓存是否成功使用。 要了解缓存的有效性,您可以通过添加一个额外属性来启用类加载日志:-Xlog:class+load:file=aot-cache.log。这将创建一个 aot-cache.log 文件,其中包含每次尝试加载类及其来源的信息。从缓存加载的类应具有“shared objects file”来源,如以下示例所示:

[0.151s][info][class,load] org.springframework.core.env.EnvironmentCapable source: shared objects file
[0.151s][info][class,load] org.springframework.beans.factory.BeanFactory source: shared objects file
[0.151s][info][class,load] org.springframework.beans.factory.ListableBeanFactory source: shared objects file
[0.151s][info][class,load] org.springframework.beans.factory.HierarchicalBeanFactory source: shared objects file
[0.151s][info][class,load] org.springframework.context.MessageSource source: shared objects file

如果 AOT 缓存无法启用,或者有大量类未从缓存加载,请确保在创建和使用缓存时满足以下条件:

  • 必须使用完全相同的 JVM。

  • 类路径必须指定为 JAR 或 JAR 列表,并避免使用目录和 * 通配符。

  • JAR 的时间戳必须保留。

  • 使用缓存时,类路径必须与创建缓存时使用的类路径相同,且顺序一致。 可以在 末尾 指定额外的 JAR 或目录(但不会被缓存)。