It is possible to create a Shared classes cache and include it in the Docker file.
The Shared classs cache can be created in a dev or pre-prod environment, or while runing some tests on the application.
Creating the cache in Pre-prod might be more effective, but dooing it with tests during the build process is much simpler.
I tested it with a Spring Boot application, and even the simple "contextLoads" test which is included with any newly generated Spring Boot project makes a huge difference.
Here is an example with tests using Maven, but the same VM options can be used in different scenarios as well.
1. Running tests with shared classes cache enabled:
You can do it in Maven with the Surefire plugin, I'm not sure how can this be done with Gradle
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xquickstart -Xshareclasses:cacheDir=classCache,name=appname -Xscmx32m </argLine>
</configuration>
</plugin>
VM Arguments: -Xquickstart -Xshareclasses:cacheDir=classCache,name=appname -Xscmx32m
- The cacheDir sub option is there to specify the cache folder to make it easier to include in the Docker image
- The name sub option is there to avoid the hardly predictable automatic cache name
- -Xscmx option is there to limit the cache size, this should be tuned for the application, there is a tradeoff between startup speed and image size
- -Xquickstart option instructs the JVM to do as much AOT as possible when used combined with the -Xshareclasses option
You can check how much of the cache size is used with the printStats subOption like this: java -jar -Xshareclasses:cacheDir=classCache,name=appname,readonly,printStats application.jar
2. Add prewarmed cache to the Docker image
Simply add the directory set by the cacheDir sub option to the image in this case classCache
ADD classCache classCache
Since these files will change every single time, classCache should be added last to the image
And run the application with the cache
ENTRYPOINT exec java -Xquickstart -Xtune:virtualized -Xshareclasses:cacheDir=classCache,name=appname,readonly -jar application.jar
VM Arguments: -Xquickstart -Xtune:virtualized -Xshareclasses:cacheDir=classCache,name=appname,readonly -jar application.jar
The cache can be specified with the classCache and name sub options, without these the JVM might create a new cache folder and ignore the one added to the image.
According to my experience the readonly option makes it a bit faster, but it's not strictly necessary. Since this cache will be dropped when the container is destroyed it's not necessary to persist the canges.
-Xquickstart and -Xtune:virtualized options are there to further optimize startup speed in the container