Add support for AppCDS and AOT#5644
Open
Alexander Maryanovsky (m-sasha) wants to merge 25 commits into
Open
Conversation
Closed
Contributor
Author
|
I haven't (re-)tested this on a demo app yet, but the tests seem to pass locally. |
Contributor
Author
|
There is an issue remaining from the previous attempt to support AppCDS where the JVM "looks at" the class files on the classpath even though they are present in the archive. On Windows this results in failing file lookups which take a long time and this negates a large part of the benefit of AppCDS (but it's still faster than without AppCDS). I'm still in conversation with the IJ/JBR team to hopefully fix this one day, but for now I guess we'll have to live with it. |
…n process of AppCdsMode.Prebuild
…sults in identical outputs
…hen running the app to create the archive in Prebuild mode.
2d10419 to
2f5c11f
Compare
Member
|
to make the CI happy, please, update the compose version in |
Konstantin (terrakok)
approved these changes
Jul 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
AppCDS and AOT are new mechanisms in the JDK/JVM which allow creating a "class archive" that helps the JVM to load classes much faster than normally, significantly reducing startup time.
Quick-start
To create/use this archive, the application needs to be run with special JVM flags.
Note that the distributable will be larger than usual because at minimum, the archive of the JRE classes needs to be packaged with the app.
The API is a new section in
compose.desktop { application { ... } }, e.g.There are currently four modes:
None
The "normal" mode where nothing special happens and everything runs as before. This is the default.
AppCdsAuto
In this mode, an AppCDS class archive is created when the end-user first runs the app.
Requires JDK 19 or later.
Advantages:
Drawbacks:
AppCdsPrebuild
In this mode Gradle executes a "training run" of the app before packaging it to create the AppCDS class archive.
Requires JDK 21 or later.
Advantages:
Drawbacks:
AotPrebuild
This mode is similar to
AppCdsPrebuild, but it uses the JDK 25 AOT feature which is an enhancement of AppCDS that adds even more information to the class archive. It improves linking and JIT warmup too.This mode also requires a "training run" of the app before packaging it to create the AOT class archive.
Requires JDK 25 or later.
Advantages:
AppCdsPrebuild.Drawbacks:
Training Run
In the "Prebuild" modes, the Compose Multiplatform Gradle plugin runs the app (the "Training Run") when packaging it for distribution to create the class archive. When it does this, it sets a system property
compose.aot.training-runtotrue, letting the app know that it's being run to create the archive. The app, when given this flag, should cause all the classes it wants to be in the archive to be loaded.This can be very simple if the developer only wants to optimize startup. In this case, and if building the distributable manually, the developer can just manually quit the app after it is run. If building automatically (e.g. on a CI/CD), the app should check for the flag, wait until it has finished starting up, and exit. Something like this will work for most apps:
We could also add some support in Compose when running with this flag.
isComposeIdlestate, so the app can wait on that.isComposeIdlebecomestrueafter startup.Of course the developer may want to include classes other than the ones used on startup. For example, there may be a feature/screen in the app that loads many classes, and therefore takes a long time when used the first time. The app should then "use" this feature (or show the screen) and then quit.
Note that when building the distributable on a CI/CD machine, it will need to be able to run the app, and therefore will need to have a graphical environment. In the future, maybe we could execute the app using
ImageComposeSceneand not require a graphical environment.Startup Time comparison on a small project
All values in milliseconds
macOS (M1 Ultra)
Cold start
Hot start (2nd run)
Windows (Dell Precision 5690)
Cold start
Hot start (2nd run)
*Executed in a such a way that the jars at the classpath with which the app was packages don't exist.
This is important due to https://youtrack.jetbrains.com/issue/JBR-9098/AppCDS-writes-local-paths-into-.jsa-archive
Fixes https://youtrack.jetbrains.com/issue/CMP-8338/Support-AppCDS-in-Compose-for-Desktop
Fixes https://youtrack.jetbrains.com/issue/CMP-10425/AOT-Compilation-for-desktop-distributables
Testing
Tested manually on a demo app.
The app is at https://github.com/m-sasha/DesktopPlaygroundAot
This should be tested by QA
Release Notes
Highlights - Desktop