Gradle uses two main directories to perform and manage its work: the Gradle user home directory and the Project root directory. The following two sections describe what is stored in each of them and how transient files and directories are cleaned up.

Gradle user home directory

The Gradle user home directory (<home directory of the current user>/.gradle by default) is used to store global configuration properties and initialization scripts as well as caches and log files. It is roughly structured as follows:

├── caches (1)
│   ├── 4.8 (2)
│   ├── 4.9 (2)
│   ├── ⋮
│   ├── jars-3 (3)
│   └── modules-2 (3)
├── daemon (4)
│   ├── ⋮
│   ├── 4.8
│   └── 4.9
├── init.d (5)
│   └── my-setup.gradle
├── jdks (6)
│   ├── ⋮
│   └── jdk-14.0.2+12
├── wrapper
│   └── dists (7)
│       ├── ⋮
│       ├── gradle-4.8-bin
│       ├── gradle-4.9-all
│       └── gradle-4.9-bin
└── gradle.properties (8)
1 Global cache directory (for everything that’s not project-specific)
2 Version-specific caches (e.g. to support incremental builds)
3 Shared caches (e.g. for artifacts of dependencies)
4 Registry and logs of the Gradle Daemon
5 Global initialization scripts
6 JDKs downloaded by the toolchain support
7 Distributions downloaded by the Gradle Wrapper
8 Global Gradle configuration properties

Cleanup of caches and distributions

Gradle automatically cleans its user home directory. By default, the cleanup runs in the background when the Gradle daemon is stopped or shuts down. If using --no-daemon, it runs in the foreground after the build session with a visual progress indicator.

The following cleanup strategies are applied periodically (by default, once every 24 hours):

  • Version-specific caches in caches/<gradle-version>/ are checked for whether they are still in use. If not, directories for release versions are deleted after 30 days of inactivity, snapshot versions after 7 days of inactivity.

  • Shared caches in caches/ (e.g. jars-*) are checked for whether they are still in use. If there’s no Gradle version that still uses them, they are deleted.

  • Files in shared caches used by the current Gradle version in caches/ (e.g. jars-3 or modules-2) are checked for when they were last accessed. Depending on whether the file can be recreated locally or would have to be downloaded from a remote repository again, it will be deleted after 7 or 30 days of not being accessed, respectively.

  • Gradle distributions in wrapper/dists/ are checked for whether they are still in use, i.e. whether there’s a corresponding version-specific cache directory. Unused distributions are deleted.

Configuring cleanup of caches and distributions

The retention periods of the various caches can be configured. Caches are classified into four categories:

  • Released wrapper distributions: Distributions and related version-specific caches that correspond to released versions (e.g. 4.6.2 or 8.0). Default retention for unused versions is 30 days.

  • Snapshot wrapper distributions: Distributions and related version-specific caches that correspond to snapshot versions (e.g. 7.6-20221130141522+0000). Default retention for unused versions is 7 days.

  • Downloaded resources: Shared caches that are downloaded from a remote repository (e.g. cached dependencies). Default retention for unused resources is 30 days.

  • Created resources: Shared caches that are created by Gradle during the course of a build (e.g. artifact transforms). Default retention for unused resources is 7 days.

The retention period for each category can be configured independently via an init script in Gradle User Home:

gradleUserHome/init.d/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        releasedWrappers.removeUnusedEntriesAfterDays = 45
        snapshotWrappers.removeUnusedEntriesAfterDays = 10
        downloadedResources.removeUnusedEntriesAfterDays = 45
        createdResources.removeUnusedEntriesAfterDays = 10
    }
}
gradleUserHome/init.d/cache-settings.gradle.kts
beforeSettings {
    caches {
        releasedWrappers.setRemoveUnusedEntriesAfterDays(45)
        snapshotWrappers.setRemoveUnusedEntriesAfterDays(10)
        downloadedResources.setRemoveUnusedEntriesAfterDays(45)
        createdResources.setRemoveUnusedEntriesAfterDays(10)
    }
}

The frequency at which cache cleanup is invoked is also configurable. There are three possible settings:

  • DEFAULT: Cleanup is performed periodically in the background (currently once every 24 hours).

  • DISABLED: Never cleanup Gradle user home. This is useful in cases where Gradle user home is ephemeral or it’s desirable to delay cleanup until an explicit point in the future.

  • ALWAYS: Cleanup is performed at the end of each build session. This is useful in cases where it’s desirable to ensure that cleanup has actually occurred before proceeding. However, this does perform cache cleanup during the build (rather than in the background) which can be an expensive operation, so this option should only be used when absolutely necessary.

gradleUserHome/init.d/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        cleanup = Cleanup.DISABLED
    }
}
gradleUserHome/init.d/cache-settings.gradle.kts
beforeSettings {
    caches {
        cleanup.set(Cleanup.DISABLED)
    }
}

Note that cache cleanup settings can only be configured via init scripts and should be placed under the init.d directory in Gradle user home. This effectively couples the configuration of cache cleanup to the Gradle user home directory those settings apply to and limits the possibility of different conflicting settings from different projects being applied to the same directory.

Sharing a Gradle user home directory between multiple versions of Gradle

It is common to share a single Gradle user home directory between multiple versions of Gradle. As stated above, there are caches in Gradle user home that are version-specific. In general, different versions of Gradle will perform maintenance on only the version-specific caches associated with each version. On the other hand, there are other caches that are shared between versions (e.g. the dependency artifact cache or the artifact transform cache). Beginning with Gradle version 8.0, the cache cleanup settings can be configured to custom retention periods. However, older versions have retention periods that are fixed (7 or 30 days depending on the cache) and so the shared caches could be accessed by versions of Gradle with different settings for the retention of cache artifacts. This means that:

  • If the retention period is not customized, all versions that perform cleanup will have the same retention periods and there will be no effect due to sharing a Gradle user home directory with multiple versions.

  • If the retention period is customized for Gradle versions greater than or equal to version 8.0 to use retention periods shorter than the previously fixed periods, there will also be no effect. The versions of Gradle aware of these settings will cleanup artifacts earlier than the previously fixed retention periods and older versions will effectively not participate in the cleanup of shared caches.

  • If the retention period is customized for Gradle versions greater than or equal to version 8.0 to use retention periods longer than the previously fixed periods, the older versions of Gradle may clean the shared caches earlier than what is configured. In this case, if it is desirable to maintain these shared cache entries for newer versions for the longer retention periods, they will not be able to share a Gradle user home directory with older versions and will need to use a separate directory.

Another consideration when sharing the Gradle user home directory with versions of Gradle before version 8.0 is that the DSL elements to configure the cache retention settings are not available in earlier versions, so this must be accounted for in any init script that is shared between versions. This can easily be handled by conditionally applying a version-compliant script. Note that the version-compliant script should reside somewhere other than the init.d directory (such as a sub-directory) so that it is not automatically applied.

gradleUserHome/init.d/cache-settings.gradle
if (GradleVersion.current() >= GradleVersion.version('8.0')) {
    apply from: "gradle8/cache-settings.gradle"
}
gradleUserHome/init.d/cache-settings.gradle.kts
if (GradleVersion.current() >= GradleVersion.version("8.0")) {
    apply(from = "gradle8/cache-settings.gradle.kts")
}
gradleUserHome/init.d/gradle8/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        releasedWrappers.removeUnusedEntriesAfterDays = 45
        snapshotWrappers.removeUnusedEntriesAfterDays = 10
        downloadedResources.removeUnusedEntriesAfterDays = 45
        createdResources.removeUnusedEntriesAfterDays = 10
    }
}
gradleUserHome/init.d/gradle8/cache-settings.gradle.kts
beforeSettings {
    caches {
        releasedWrappers { setRemoveUnusedEntriesAfterDays(45) }
        snapshotWrappers { setRemoveUnusedEntriesAfterDays(10) }
        downloadedResources { setRemoveUnusedEntriesAfterDays(45) }
        createdResources { setRemoveUnusedEntriesAfterDays(10) }
    }
}

Cache marking

Beginning with Gradle version 8.1, Gradle supports marking caches with a CACHEDIR.TAG file. It follows the format described in the Cache Directory Tagging Specification. The purpose of this file is to allow tools to identify the directories that do not need to be searched or backed up. By default, the directories caches, wrapper/dists, daemon, and jdks in the Gradle user home directory are marked with this file.

Configuring cache marking

The cache marking feature can be configured via an init script in the Gradle user home directory:

gradleUserHome/init.d/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        // Disable cache marking for all caches
        markingStrategy = MarkingStrategy.NONE
    }
}
gradleUserHome/init.d/cache-settings.gradle.kts
beforeSettings {
    caches {
        // Disable cache marking for all caches
        markingStrategy.set(MarkingStrategy.NONE)
    }
}

Note that cache marking settings can only be configured via init scripts and should be placed under the init.d directory in Gradle user home. This effectively couples the configuration of cache marking to the Gradle user home directory those settings apply to and limits the possibility of different conflicting settings from different projects being applied to the same directory.

Project root directory

The project root directory contains all source files that are part of your project. In addition, it contains files and directories that are generated by Gradle such as .gradle and build. While the former are usually checked in to source control, the latter are transient files used by Gradle to support features like incremental builds. Overall, the anatomy of a typical project root directory looks roughly as follows:

├── .gradle (1)
│   ├── 4.8 (2)
│   ├── 4.9 (2)
│   └── ⋮
├── build (3)
├── gradle
│   └── wrapper (4)
├── gradle.properties (5)
├── gradlew (6)
├── gradlew.bat (6)
├── settings.gradle or settings.gradle.kts (7)
├── subproject-one (8)
|   └── build.gradle or build.gradle.kts (9)
├── subproject-two (8)
|   └── build.gradle or build.gradle.kts (9)
└── ⋮
1 Project-specific cache directory generated by Gradle
2 Version-specific caches (e.g. to support incremental builds)
3 The build directory of this project into which Gradle generates all build artifacts.
4 Contains the JAR file and configuration of the Gradle Wrapper
5 Project-specific Gradle configuration properties
6 Scripts for executing builds using the Gradle Wrapper
7 The project’s settings file where the list of subprojects is defined
8 Usually a project is organized into one or multiple subprojects
9 Each subproject has its own Gradle build script

Project cache cleanup

From version 4.10 onwards, Gradle automatically cleans the project-specific cache directory. After building the project, version-specific cache directories in .gradle/<gradle-version>/ are checked periodically (at most every 24 hours) for whether they are still in use. They are deleted if they haven’t been used for 7 days.