Gradle 8.10.2 is the second patch release for Gradle 8.10.
It fixes the following issues:
- #30472 Investigate possibly broken 8.10.1
- #30477 Kotlin Mutliplatform build with reused daemon fails with “Cannot query the value of task ‘:compileKotlinWindows’ property ‘kotlinNativeBundleBuildService’ because it has no value available.”
- #30497 DefaultTaskCollection#configureEach(Action) on task set cannot be executed in the current context
Issues fixed in the first patch release:
- #30239 Gradle 8.10 Significantly Slower Due to Dependency Resolution
- #30272 Broken equals() contract for LifecycleAwareProject
- #30385 Gradle should not validate isolated projects when isolated projects is disabled
We recommend users upgrade to 8.10.2 instead of 8.10.
Gradle now supports running on Java 23.
This release introduces performance and reporting improvements to the configuration cache, including a significant reduction in the cache file size and accelerated cache loading times. There are also updates to build authoring APIs.
Starting with Gradle 9.0, Gradle will require JVM 17 or newer to run. In Gradle 8.10, warnings will be emitted when running on older JVM versions.
We would like to thank the following community members for their contributions to this release of Gradle: Björn Kautler, Craig Andrews, gotovsky, Jeff, Kirill Gavrilov, Madalin Valceleanu, Sergei Vorobev, Thach Le, Thad Guidry
Be sure to check out the public roadmap for insight into what’s planned for future releases.
Table Of Contents
Upgrade instructions
Switch your build to use Gradle 8.10.2 by updating the Wrapper in your project:
./gradlew wrapper --gradle-version=8.10.2
See the Gradle 8.x upgrade guide to learn about deprecations, breaking changes, and other considerations when upgrading to Gradle 8.10.2.
For Java, Groovy, Kotlin, and Android compatibility, see the full compatibility notes.
New features and usability improvements
Full Java 23 support
With this release, Gradle supports running on Java 23. This means you can now use Java 23 for the daemon in addition to toolchains.
Note that certain features that rely on third-party tools, such as PMD and Scala, may not work with Java 23 yet.
For details, see the full compatibility documentation.
Configuration cache improvements
The configuration cache improves build performance by caching the result of the configuration phase. Gradle uses the configuration cache to skip the configuration phase entirely when nothing that affects the build configuration has changed.
Reduced cache entry sizes and faster loading times
In Gradle 8.10, strings stored in the configuration cache are deduplicated at store time, meaning each unique string is written only once per file.
In addition to significantly reducing cache entry size, these changes have a significant impact on build performance when using configuration cache:
- With less data to encrypt/decrypt, execution times for cache-hit builds are reduced by around 28%, and for cache-miss builds by about 7%.
- Sharing strings reduces memory allocation by approximately 13% for cache-hit builds.
This is possible with string deduplication because less data needs to be written to and read from disk, and each string can be read once and then shared.
In general, larger and more complex builds benefit the most from these improvements.
The improvements are quantified with metrics from three different projects of varying sizes and complexities:
Small project (NowInAndroid, 33 modules)
Release | Cache-Hit Configuration Time | Cache-Miss Configuration Time | Storage | Memory allocations |
8.9 | 295.87ms | 2,297.11ms | 12M | 257.75M |
8.10 | 226.46ms | 2,233.88ms | 5.2M | 241.62M |
Improvement | -23.46% | -2.75% | -57.4% | -6.3% |
Medium size project (Gradle, 184 modules)
Release | Cache-Hit Configuration Time | Cache-Miss Configuration Time | Storage | Memory allocations |
8.9 | 2,299.77ms | 16,033.74ms | 131M | 1.48G |
8.10 | 1,567.09ms | 14,474.11ms | 17M | 1.21G |
Improvement | -31.86% | -9.73% | -86.9% | -18.1% |
Release | Cache-Hit Configuration Time | Cache-Miss Configuration Time | Storage | Memory allocations |
8.9 | 24,547.75ms | 130,060.61ms | 1.3G | 18.55G |
8.10 | 17,652.50ms | 120,083.64ms | 372M | 15.97G |
Improvement | -28.09% | -7.67% | -72.6% | -13.9% |
Enhanced Configuration Cache reporting
Adopting the configuration cache can require updates to your build logic to meet compatibility requirements. When this feature is enabled, Gradle will report any incompatibilities via the Configuration Cache report.
Report provides invalidation reason for cache misses
In Gradle 8.10, the Configuration Cache report now includes the invalidation reason in case of a cache miss, similar to the console output:
Report lists incompatible tasks
Since Gradle 7.4, it is possible to mark tasks as not compatible with the Configuration Cache. When these tasks participate in a build invocation, the cache entry will not be stored.
In Gradle 8.10, any incompatible tasks executed as part of the invocation are shown in a new dedicated section of the report:
Report is copy-paste friendly
Finally, the report content is copy-friendly in Gradle 8.10. Copying and pasting the description of problems now produces Markdown-like text that preserves meaningful indentations:
- [error] Project `:foo` cannot dynamically lookup a property in the parent project `:`
- property `prop` of `:foo`
- build file 'foo/build.gradle'
Gradle provides rich APIs for plugin authors and build engineers to develop custom build logic.
Improved behavior and callback execution for the GradleLifecycle API
The recently added GradleLifecycle API is part of Gradle’s core API and is used to manage and interact with a Gradle build’s lifecycle events.
Previously, the GradleLifecycle.beforeProject{}
callback was executed right before the project evaluation.
The issue is that the results of GradleLifecycle.beforeProject{}
execution are not observable within cross-project access API invocations, such as Project.allprojects{}
, Project.getAllprojects{}
, Project.subprojects{}
, etc. Some builds may depend on the eagerness of these APIs, necessitating additional build logic changes when migrating to the new GradleLifecycle
callbacks.
For example in:
// settings.gradle.kts
gradle.lifecycle.beforeProject {
println("Lifecycle :$name")
extra["foo"] = "bar" // Set project state
}
rootProject.name = "root"
include(":a")
include(":b")
// build.gradle.kts
allprojects { // Eager cross-project access API
println("Allprojects :$name")
println("Foo = ${extra["foo"]}") // Access project state
}
The output is:
Lifecycle :root
Allprojects :root
Foo = bar
Allprojects :a
Foo = null
Allprojects :b
Foo = null
Lifecycle :a
Lifecycle :b
Where the result of setting an extra property in GradleLifecycle.beforeProject{}
is not observable in Project.allprojects{}
.
In this release, the behavior of this incubating API has changed. If the mutable state of the project is accessed in cross-project access APIs, the execution order will change, such that GradleLifecycle.beforeProject{}
is executed before mutable state access.
Now, the result of running the above example would be:
Lifecycle :root
Allprojects :root
Foo = bar
Allprojects :a
Lifecycle :a
Foo = bar
Allprojects :b
Lifecycle :b
Foo = bar
Otherwise, if only the project’s immutable state is accessed, the GradleLifecycle.beforeProject{}
callback will be executed in the previous order.
Preemptive warnings for outdated JVM versions in Gradle 9.0
Starting with Gradle 9.0, Gradle will require JVM 17 or newer to run. Gradle will still support compiling Java code to target JVM version 6 or later. For more details, see the upgrade guide.
With this release, Gradle will start emitting warnings when using older JVM versions:
Executing Gradle on JVM versions 16 and lower has been deprecated. This will fail with an error in Gradle 9.0. Use JVM 17 or greater to execute Gradle. Projects can continue to use older JVM versions via toolchains.
Matching specific vendors with daemon JVM criteria
Daemon JVM critiera supports specifying the JVM vendor. When considering available JVM toolchains, Gradle will only choose a toolchain compatible with both the specified JVM vendor and version.
If no JVM vendor is specified in the criteria, any vendor is considered compatible.
This feature is still incubating and may change in future versions of Gradle.
Promoted features
Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backward compatibility. See the User Manual section on the “Feature Lifecycle” for more information.
The following are the features that have been promoted in this Gradle release.
Stable configuration options for the Java Gradle Plugin plugin
The website
and vcsUrl
properties of gradlePlugin
extension are now stable.
Fixed issues
3 issues have been fixed in Gradle 8.10.2.
- [#30497] - DefaultTaskCollection#configureEach(Action) on task set cannot be executed in the current context since 8.10.1
- [#30477] - Kotlin Mutliplatform build with reused daemon fails with “Cannot query the value of task ‘:compileKotlinWindows’ property ‘kotlinNativeBundleBuildService’ because it has no value available.”
- [#30472] - Investigate possibly broken 8.10.1
Known issues
Known issues are problems that were discovered post-release that are directly related to changes made in this release.
External contributions
We love getting contributions from the Gradle community. For information on contributing, please see gradle.org/contribute.
Reporting problems
If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you’re not sure you’re encountering a bug, please use the forum.
We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.