Open-source project
GradleUp/shadow avatar
GradleUp/shadow

GradleUp/shadow: fat JARs for Gradle, and the plugin ID migration nobody mentions

Gradle plugin for creating fat/uber JARs, transforming files, relocating packages, and optimizing with R8/ProGuard. The Gradle counterpart to Maven Shade Plugin.

4,240 stars426 forksKotlinApache-2.0

At a glance

What is it?
GradleUp/shadow builds uber JARs, relocates packages and runs R8 or ProGuard over the result. It is the Gradle answer to Maven Shade, and its compatibility matrix is the part most builds get wrong.
Who is it for?
Adopt GradleUp/shadow if you ship a JVM application as a single archive and need relocation or shrinking in the same step. Do not adopt it if you are still on Gradle 8.x or Java 8, or if you are porting a Maven Shade build that depends on Shade's own filter semantics.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What GradleUp/shadow actually builds

A fat JAR is one archive holding your classes plus every runtime dependency, so a JVM application starts with `java -jar` instead of a classpath assembled by a launcher script. Gradle has no built-in task for that. Shadow adds one, and the README describes the plugin as covering four jobs: creating fat or uber JARs, transforming files, relocating packages, and optimizing with R8 or ProGuard. Relocation is the part that separates it from a plain `Jar` task with dependencies copied in. If two dependencies ship the same class path, or a dependency bundles a shaded copy of a library you also depend on, relocation rewrites the package names so the copies stop colliding. The audience is JVM projects on Gradle: application authors distributing a runnable archive, library authors who need a self-contained artifact, and teams whose output has to pass through a shrinker before release. The README positions it explicitly as the Gradle counterpart to Maven Shade Plugin, which tells you the mental model it expects you to bring.

Relocation, file transformation and the R8/ProGuard step

The plugin works on the JAR level. It collects the project's own output and its runtime dependencies, then writes a merged archive, applying relocations and file transformations to the entries as they are copied. Relocation is a package prefix rewrite, so it touches class files, resource paths and the string references that point at them; a relocation rule that misses a resource path is the classic way to produce an archive that builds cleanly and fails at runtime. File transformation sits alongside it: entries can be rewritten or excluded during the merge rather than patched afterwards. The optimization stage hands the merged output to R8 or ProGuard, which strips unused classes and renames what remains. That ordering matters. Shrinking a fat JAR is different from shrinking your own classes, because the shrinker now sees the whole dependency graph and needs keep rules for anything reached reflectively. The repository is Kotlin, and the top-level layout (api/, src/, docs/, mkdocs.yml) suggests a published API module plus a documentation site built with MkDocs. The README does not document rollback behaviour or a dry-run mode for the merge, so treat the first run on an existing build as something to inspect by hand.

Installing GradleUp/shadow and building a first fat JAR

The README points at the Gradle Plugin Portal and Maven Central for the artifact `com.gradleup.shadow:shadow-gradle-plugin`, and the user guide lives at gradleup.com/shadow. Apply the plugin by ID in the build script. The ID you choose is not cosmetic: the compatibility matrix lists `com.github.johnrengelman.shadow` for 8.0.0 and later, and `com.gradleup.shadow` from 8.3.0 onward, after maintenance moved to the GradleUp organization. The README recommends switching to the new ID and updating to the latest version. The plugin ID below is the one the matrix pairs with 8.3.0 and later.

kotlin
plugins {
    id("com.gradleup.shadow") version "9.6.1"
}

Applying the plugin registers its tasks. The README excerpt does not name the task, so check what was registered before wiring anything into CI. Version constraints come from the same matrix and are the most common source of a failed first build: 9.5.0 and later require Gradle 9.2 and Java 17, while 9.3.0 and later require Gradle 9.0. If your toolchain is older, the matrix tells you which Shadow line still fits rather than leaving you to guess. Once the packaging task runs, the output is a single archive under the build directory. Open it and check that relocated packages actually moved and that no duplicate class path survived the merge.

The compatibility matrix is the real adoption cost

Shadow's version numbers are tied to Gradle and Java floors, and those floors move. The matrix starts at 8.0.0 with Gradle 8.0 and Java 8, then 9.0.0 raises the minimum Gradle to 8.11 and Java to 11, 9.2.0 raises Java to 17, 9.3.0 raises Gradle to 9.0, 9.5.0 raises it again to 9.2, and 9.7.0 lists Gradle 9.4. A build that upgrades Shadow without upgrading Gradle will fail at configuration time, and the failure will look like a plugin resolution problem rather than a version floor. There is a second cost: the plugin ID changed mid-history. Projects that predate the transfer still declare `com.github.johnrengelman.shadow`, which the matrix ties to 8.0.0 and later. The README recommends the new ID, but a migration touches every build script and any convention plugin or build logic that references the old one. The README does not state whether the old ID continues to receive fixes, so a team staying on it is making an assumption the documentation does not confirm.

Where Shadow is the wrong tool

A fat JAR is not always the right deliverable. If your application is a Spring Boot service, the Boot plugin produces its own executable archive with a nested classloader layout, and Shadow's flat merge does not reproduce that structure. If you ship to a container, a layered image or a `jlink` runtime may serve you better than one large archive. Relocation also has a cost that is easy to underestimate: rewriting package names changes stack traces and any string that names a class, so logging configuration and reflection-heavy frameworks need attention. And if your problem is only that the classpath is long, a manifest `Class-Path` entry or a launcher script solves it without merging anything. The README does not document rollback for a failed merge or a dry-run mode, which means the first pass over an unfamiliar dependency graph is a manual inspection job. Shadow is a packaging tool, not a dependency-conflict resolver; it makes collisions survivable by renaming, and it will happily produce an archive whose duplicates you never noticed.

Shadow against Maven Shade and Gradle's own Jar task

The README names Maven Shade Plugin as the counterpart, and the difference is mostly in the build system rather than the algorithm. Shade is configured through Maven's plugin XML with its own filter, relocation and resource-transformer vocabulary. Shadow exposes the same broad capabilities through Gradle's task model, so configuration lives in the build script and composes with Gradle's dependency resolution. Porting a Shade build means translating filter semantics, not copying configuration, and the README does not claim a one-to-one mapping. The other comparison is against Gradle's own `Jar` task. A plain `Jar` can include dependency contents, but it does not relocate packages, does not transform individual entries, and does not run a shrinker. If you only need one archive and your dependencies do not collide, the built-in task is sufficient and adds no plugin to your build. Shadow earns its place when relocation or R8/ProGuard shrinking is part of the release pipeline.

Licence, maintenance and what a version bump costs

Shadow is Apache-2.0, which permits commercial and closed-source use and requires the usual notice and licence retention; the repository carries a LICENSE file at the top level. That is a statement about the licence text, not legal advice, and a team with specific obligations should read the file rather than a summary. On maintenance, the repository is not archived, and the last push was on 2026-09-23. Recent releases are 9.6.1 on 2026-07-22, 9.6.0 on 2026-07-16 and 9.5.1 on 2026-07-06, so the release cadence is visible in the release list. The upgrade cost is dominated by the compatibility matrix rather than by API churn: each Shadow line carries a Gradle and Java floor, and moving up a line means moving your build toolchain with it. The old plugin ID adds a second, one-time cost for projects that predate the transfer. The repository has a CHANGELOG.md and a RELEASING.md, so the release history is documented in-tree rather than only in the README.

Editorial conclusion

Adopt GradleUp/shadow if you ship a JVM application as a single archive and need relocation or shrinking in the same step. Do not adopt it if you are still on Gradle 8.x or Java 8, or if you are porting a Maven Shade build that depends on Shade's own filter semantics. Before anything else, verify which plugin ID your build script uses, because com.github.johnrengelman.shadow is the pre-transfer ID and com.gradleup.shadow is the one the compatibility matrix pairs with 8.3.0 and later.

Frequently asked questions

What is the GradleUp/shadow Gradle plugin?

It is a Gradle plugin for creating fat or uber JARs, transforming files, relocating packages and optimizing with R8 or ProGuard. The README describes it as the Gradle counterpart to Maven Shade Plugin.

Which plugin ID should a new GradleUp/shadow build use?

The compatibility matrix pairs `com.gradleup.shadow` with 8.3.0 and later, while `com.github.johnrengelman.shadow` is the earlier ID tied to 8.0.0 and later. The README recommends switching to the new ID and updating to the latest version.

Which Gradle and Java versions does GradleUp/shadow require?

The matrix lists 9.5.0 and later as requiring Gradle 9.2 and Java 17, 9.3.0 and later as requiring Gradle 9.0, and 9.2.0 and later as requiring Java 17. Older lines have lower floors, starting at Gradle 8.0 and Java 8 for 8.0.0.

Is GradleUp/shadow the same project as the johnrengelman shadow plugin?

Yes. The README states the plugin was previously developed by @johnrengelman under the ID `com.github.johnrengelman.shadow` before maintenance was transferred to the GradleUp organization.

What licence does GradleUp/shadow use?

The repository is licensed under Apache-2.0 and carries a LICENSE file at the top level. The README does not add licence terms beyond that.

Official sources

  1. GradleUp/shadow on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/gradleup-shadow.svg)](https://hysenlabs.com/projects/gradleup-shadow)