Skip to content

fix: disambiguate duplicate dependency JARs by content hash instead of file size - #4528

Open
sideeffffect wants to merge 1 commit into
GoogleContainerTools:masterfrom
sideeffffect:dependency-jar-dedup-content-hash
Open

fix: disambiguate duplicate dependency JARs by content hash instead of file size#4528
sideeffffect wants to merge 1 commit into
GoogleContainerTools:masterfrom
sideeffffect:dependency-jar-dedup-content-hash

Conversation

@sideeffffect

Copy link
Copy Markdown

Issue

When several dependency JARs share the same filename, jib renames the duplicates so they don't overwrite each other under libs/ in the image. Today the disambiguating suffix is the file size (Files.size(...)):

jarName = jarName.replaceFirst("\\.jar$", "-" + Files.size(file)) + ".jar";

File size is not a reliable discriminator. Two genuinely different JARs that happen to share a filename can also happen to have the exact same size, in which case one still silently overwrites the other — producing NoClassDefFoundError at runtime. This is the same class of problem originally reported in #3331; the size-based fix narrowed it but didn't close it.

Fix

Use a short prefix of the SHA-256 of the JAR contents as the suffix instead, computed via jib-core's existing Digests utility. A content hash distinguishes distinct JARs regardless of their size, while staying deterministic across builds (so it doesn't hurt reproducibility or layer caching). The digest is truncated to 12 hex characters to keep filenames reasonable — more than enough to tell apart the handful of same-named JARs in a single build.

The renaming exists in two places that are required to stay in sync:

  • jib-coreJavaContainerBuilder
  • jib-plugins-commonPluginConfigurationProcessor (used by both the Maven and Gradle plugins)

Both are updated identically, via a small private computeContentHash(Path) helper in each.

Tests

Updated the two existing duplicate-JAR tests to assert the new content-hash suffixes (JavaContainerBuilderTest, PluginConfigurationProcessorTest). Verified locally:

  • :jib-core:test --tests JavaContainerBuilderTest
  • :jib-plugins-common:test --tests PluginConfigurationProcessorTest
  • verifyGoogleJavaFormat and errorprone/NullAway (via compileJava) ✅

CHANGELOGs updated for jib-core, jib-maven-plugin, and jib-gradle-plugin.

Fixes the remaining collision described in #3331.

@google-cla

google-cla Bot commented Sep 1, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

…f file size

When multiple dependency JARs share the same filename, jib renames the
duplicates by appending a suffix so they don't overwrite each other in the
image. Until now that suffix was the file size (Files.size), which is not a
reliable discriminator: two genuinely different JARs that happen to share a
filename can also happen to have the exact same size, in which case one still
silently overwrites the other, leading to NoClassDefFoundError at runtime.

Use a short prefix of the SHA-256 of the JAR contents instead, computed via
jib-core's existing Digests utility. A content hash distinguishes distinct
JARs regardless of size, while remaining deterministic across builds. The
digest is truncated to 12 hex chars to keep filenames reasonable.

The two call sites (JavaContainerBuilder and PluginConfigurationProcessor,
which must stay in sync) are both updated, along with the affected tests and
the jib-core / jib-maven-plugin / jib-gradle-plugin changelogs.

See GoogleContainerTools#3331
@sideeffffect
sideeffffect force-pushed the dependency-jar-dedup-content-hash branch from 3bfd8d0 to 5a36e09 Compare September 1, 2026 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant