JVM AOT 缓存
提前编译缓存(AOT Cache)是JVM的一项功能,通过JEP 483在Java 24中引入,该功能有助于减少Java应用程序的启动时间和内存占用。AOT缓存是类数据共享(Class Data Sharing, CDS)的自然演变。Spring框架同时支持CDS和AOT缓存,如果所使用的JVM版本(Java 24及以上)支持AOT缓存,建议使用后者。
要使用此功能,需要为应用程序的特定类路径创建一个AOT缓存。可以在已部署的实例上创建该缓存,或者在训练过程中创建缓存(例如,在打包应用程序时),这要归功于Spring Framework提供的钩子点,以便简化此类用例。一旦缓存可用,用户应通过JVM标志选择使用它。
如果你使用的是Spring Boot,强烈建议利用其可执行JAR文件解压支持,该支持专为满足AOT缓存和CDS的类加载需求而设计。
创建缓存
当应用程序退出时,通常可以创建一个AOT缓存。Spring框架提供了一种运行模式,在这种模式下,一旦ApplicationContext被刷新,进程就可以自动退出。在这种模式下,所有非延迟初始化的单例对象都已经被实例化,并且InitializingBean#afterPropertiesSet回调方法也被调用过;但是单例的生命周期尚未开始,ContextRefreshedEvent也尚未被发布。
在训练运行期间创建缓存时,可以指定 -Dspring.context.exit=onRefresh 这一 JVM 标志来启动Spring应用程序,等到 ApplicationContext 被刷新后,该应用程序就会退出:
- AOT cache (Java 25+)
- AOT cache (Java 24)
- CDS
java -XX:AOTCacheOutput=app.aot -Dspring.context.exit=onRefresh -jar application.jar ...
# 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 ...
从 Java 25 开始,AOT 缓存会存储多种信息,其中包括 方法性能分析数据。因此,为了充分利用这一功能,建议为那些经历过类似生产环境工作流程的应用程序创建 AOT 缓存,而不是使用 -Dspring.context.exit=onRefresh 标志(该标志仅用于优化应用程序的启动过程)。
使用缓存
一旦缓存文件创建完成,您就可以使用它来更快地启动您的应用程序:
- AOT cache
- 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文件,其中包含类的加载信息及其源代码。从缓存中加载的类应该具有“共享对象文件”作为其来源,如下例所示:
[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文件的 timestamp(时间戳)必须保持不变。
-
使用缓存时,类路径必须与创建缓存时使用的类路径相同,并且顺序也必须一致。可以在末尾再指定额外的JAR文件或目录(但这些文件或目录不会被缓存)。