The Java Developer's Disk: Cleaning ~/.m2 and ~/.gradle
Maven and Gradle cache every dependency version you have ever resolved. Where ~/.m2 and ~/.gradle sit, typical sizes, and what is safe to delete.
If you’ve written Java, Kotlin, or Scala for more than a couple of years, run this before reading any further:
du -sh ~/.m2/repository
du -sh ~/.gradle/caches
20–60 GB combined is ordinary. Neither number includes the per-project build/ and target/
directories scattered across every repository you’ve cloned, which is a separate problem covered at
the end.
Maven’s ~/.m2/repository: every version, forever
Maven’s local repository is a flat, global store of every artifact — every group, every version — that any project on this machine has ever resolved. There is no built-in expiry and no automatic pruning. A dependency you used for one experimental branch three years ago is still sitting there at its exact version, next to the version you actually use today.
# The heaviest groups, usually the ones you'd expect
du -sh ~/.m2/repository/org/* | sort -hr | head -20
Safe to delete entirely. Maven re-downloads whatever the next build actually needs from your
configured repositories (Maven Central, plus anything in your settings.xml). The cost is your next
build for each project resolving its dependency tree fresh over the network — slower once, not
broken.
rm -rf ~/.m2/repository
If you want to keep it but reclaim most of the space, snapshot versions (anything ending
-SNAPSHOT) are the highest-value target — they’re rebuilt constantly and old ones are almost never
referenced again:
find ~/.m2/repository -name "*-SNAPSHOT" -type d
Gradle’s ~/.gradle/caches: similar idea, worse layout
Gradle’s global cache is organized by Gradle version first, then by module — which means, exactly like JetBrains IDEs, every Gradle version you’ve ever used left its own full cache behind:
ls ~/.gradle/caches/
# 7.6 8.0 8.4 8.7 8.9 modules-2 jars-9 ...
Directories named after a Gradle version (7.6, 8.4, and so on) are safe to remove if your
projects have all moved to a newer wrapper version — check gradle/wrapper/gradle-wrapper.properties
in your active projects if you’re unsure which versions are still in use.
modules-2 is the dependency cache proper, shared across all Gradle versions, and functions exactly
like Maven’s repository: safe to delete, everything re-downloads.
rm -rf ~/.gradle/caches
Do not delete ~/.gradle/wrapper — that’s the actual Gradle distribution .zip files your
projects’ wrapper scripts point at. Deleting it just means those get re-downloaded too on next
build, which is harmless but slower than it needs to be; it’s not dangerous, just worth knowing
it’s a separate folder from caches.
The build/ and target/ directories you’re forgetting
Both build systems also write per-project output — Gradle’s build/, Maven’s target/ — inside
every repository on disk, not in a global cache location. These are the equivalent of Rust’s
target/: regenerable, and only worth deleting per-project because a global find across your
whole disk is the only way to catch the ones in repos you haven’t opened in months.
# Every build/ or target/ directory across your home folder, largest first
find ~ -type d \( -name "build" -o -name "target" \) -not -path "*/node_modules/*" -exec du -sh {} \; 2>/dev/null | sort -hr | head -20
Delete individually once you’ve confirmed each one sits next to an actual pom.xml or
build.gradle — the same filenames show up in non-Java projects too (Rust’s target/ is the most
common collision), so don’t blanket-delete without checking.
What’s actually safe here, summarized
| Location | What it is | Safe to delete? |
|---|---|---|
~/.m2/repository | Global Maven dependency cache | Yes, fully regenerable |
~/.gradle/caches/<old-version> | Per-Gradle-version cache | Yes, if that version is unused |
~/.gradle/caches/modules-2 | Global Gradle dependency cache | Yes, fully regenerable |
~/.gradle/wrapper | Actual Gradle distributions | Leave it — re-downloads are slow, not dangerous |
<project>/build, <project>/target | Per-project build output | Yes, per project |
DevCruft, the free developer-focused Mac app we’re building, is intended to find both global caches
and every stray build//target/ directory across your disk in one scan, ranked by size and
last-modified date, so you’re not writing find one-liners by hand. Until it’s ready, copy the
commands above — they’re free and they work. You can join the waitlist to hear when it
launches.
For the rest of the language-ecosystem caches, see the section on Rust, Go and Python in the full storage guide, or the dedicated Rust, Go and Python cache cleanup guide.