HBASE-30211 Exclude dnsjava InetAddressResolver SPI from shaded jars - #8559
Merged
Conversation
dnsjava is a multi-release jar: its InetAddressResolverProvider service file sits at the root, but the provider class ships only under META-INF/versions/18. Shade rewrites that class's bytecode to the relocated name and leaves its jar entry path alone, and the shaded jar is not multi-release, so the merged service file names a class no classloader can load. Since JEP 418 made this a JVM level SPI in Java 18, the first name lookup fails and takes down all DNS resolution in the process, not just HBase calls. Drop the service file in the existing dnsjava filter. The provider is opt-in behind org.dnsjava.spi.enable, so nothing depends on it, and all relocated dnsjava classes stay. Guard it in ensure-jars-have-correct-contents.sh. Static rather than runtime, since precommit and nightly build on JDK 8, 11 and 17 where the SPI is never consulted.
There was a problem hiding this comment.
Pull request overview
This PR addresses a Java 18+ runtime failure caused by a shaded InetAddressResolverProvider service entry that points to a provider class that is not loadable from the shaded jar, causing InetAddress DNS lookups to throw ServiceConfigurationError. The fix is applied at shading time and reinforced via invariants checks.
Changes:
- Excludes
META-INF/services/java.net.spi.InetAddressResolverProviderfrom shaded output fordnsjava:dnsjava. - Adds an invariants check to fail the build if a shaded artifact declares the
InetAddressResolverProviderservice. - Applies the invariants check in both shaded invariants modules (with- and without-Hadoop).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| hbase-shaded/pom.xml | Extends the dnsjava shade filter to exclude the problematic InetAddressResolverProvider service file. |
| hbase-shaded/hbase-shaded-with-hadoop-check-invariants/src/test/resources/ensure-jars-have-correct-contents.sh | Adds a jar-contents invariant rejecting shaded jars that declare the InetAddressResolverProvider service. |
| hbase-shaded/hbase-shaded-check-invariants/src/test/resources/ensure-jars-have-correct-contents.sh | Adds the same jar-contents invariant in the non-Hadoop invariants module. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Member
Author
|
Thanks @liuxiaocs7 for taking a look! |
junegunn
added a commit
that referenced
this pull request
Aug 26, 2026
…8559) dnsjava is a multi-release jar: its InetAddressResolverProvider service file sits at the root, but the provider class ships only under META-INF/versions/18. Shade rewrites that class's bytecode to the relocated name and leaves its jar entry path alone, and the shaded jar is not multi-release, so the merged service file names a class no classloader can load. Since JEP 418 made this a JVM level SPI in Java 18, the first name lookup fails and takes down all DNS resolution in the process, not just HBase calls. Drop the service file in the existing dnsjava filter. The provider is opt-in behind org.dnsjava.spi.enable, so nothing depends on it, and all relocated dnsjava classes stay. Guard it in ensure-jars-have-correct-contents.sh. Static rather than runtime, since precommit and nightly build on JDK 8, 11 and 17 where the SPI is never consulted. Signed-off-by: Xiao Liu <liuxiaocs@apache.org>
junegunn
added a commit
that referenced
this pull request
Aug 26, 2026
…8559) dnsjava is a multi-release jar: its InetAddressResolverProvider service file sits at the root, but the provider class ships only under META-INF/versions/18. Shade rewrites that class's bytecode to the relocated name and leaves its jar entry path alone, and the shaded jar is not multi-release, so the merged service file names a class no classloader can load. Since JEP 418 made this a JVM level SPI in Java 18, the first name lookup fails and takes down all DNS resolution in the process, not just HBase calls. Drop the service file in the existing dnsjava filter. The provider is opt-in behind org.dnsjava.spi.enable, so nothing depends on it, and all relocated dnsjava classes stay. Guard it in ensure-jars-have-correct-contents.sh. Static rather than runtime, since precommit and nightly build on JDK 8, 11 and 17 where the SPI is never consulted. Signed-off-by: Xiao Liu <liuxiaocs@apache.org>
junegunn
added a commit
that referenced
this pull request
Aug 26, 2026
…8559) dnsjava is a multi-release jar: its InetAddressResolverProvider service file sits at the root, but the provider class ships only under META-INF/versions/18. Shade rewrites that class's bytecode to the relocated name and leaves its jar entry path alone, and the shaded jar is not multi-release, so the merged service file names a class no classloader can load. Since JEP 418 made this a JVM level SPI in Java 18, the first name lookup fails and takes down all DNS resolution in the process, not just HBase calls. Drop the service file in the existing dnsjava filter. The provider is opt-in behind org.dnsjava.spi.enable, so nothing depends on it, and all relocated dnsjava classes stay. Guard it in ensure-jars-have-correct-contents.sh. Static rather than runtime, since precommit and nightly build on JDK 8, 11 and 17 where the SPI is never consulted. Signed-off-by: Xiao Liu <liuxiaocs@apache.org>
junegunn
added a commit
that referenced
this pull request
Aug 26, 2026
…8559) dnsjava is a multi-release jar: its InetAddressResolverProvider service file sits at the root, but the provider class ships only under META-INF/versions/18. Shade rewrites that class's bytecode to the relocated name and leaves its jar entry path alone, and the shaded jar is not multi-release, so the merged service file names a class no classloader can load. Since JEP 418 made this a JVM level SPI in Java 18, the first name lookup fails and takes down all DNS resolution in the process, not just HBase calls. Drop the service file in the existing dnsjava filter. The provider is opt-in behind org.dnsjava.spi.enable, so nothing depends on it, and all relocated dnsjava classes stay. Guard it in ensure-jars-have-correct-contents.sh. Static rather than runtime, since precommit and nightly build on JDK 8, 11 and 17 where the SPI is never consulted. Signed-off-by: Xiao Liu <liuxiaocs@apache.org>
junegunn
added a commit
that referenced
this pull request
Aug 26, 2026
…8559) dnsjava is a multi-release jar: its InetAddressResolverProvider service file sits at the root, but the provider class ships only under META-INF/versions/18. Shade rewrites that class's bytecode to the relocated name and leaves its jar entry path alone, and the shaded jar is not multi-release, so the merged service file names a class no classloader can load. Since JEP 418 made this a JVM level SPI in Java 18, the first name lookup fails and takes down all DNS resolution in the process, not just HBase calls. Drop the service file in the existing dnsjava filter. The provider is opt-in behind org.dnsjava.spi.enable, so nothing depends on it, and all relocated dnsjava classes stay. Guard it in ensure-jars-have-correct-contents.sh. Static rather than runtime, since precommit and nightly build on JDK 8, 11 and 17 where the SPI is never consulted. Signed-off-by: Xiao Liu <liuxiaocs@apache.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Jira
https://issues.apache.org/jira/browse/HBASE-30211
Description
hbase-shaded-clientships aMETA-INF/services/java.net.spi.InetAddressResolverProvidernaming a class that no classloader can load. On Java 18+ the JVM reads that declaration on the first name lookup, so everyInetAddresscall in the process throws, not just HBase calls.Three things combine:
DnsjavaInetAddressResolverProviderships only underMETA-INF/versions/18/.org.xbill. It rewrites the versioned class's bytecode to the relocated name but leaves its jar entry path alone, so the name and the path disagree.ServicesResourceTransformerthen writes the merged service file naming the relocated class.Multi-Release: true, so everything underMETA-INF/versions/**is invisible to the JVM regardless.JEP 418 introduced the SPI in Java 18, which is why 11 and 17 are unaffected.
Affected versions
dnsjava 3.6.0 added the provider, and Hadoop 3.4.1 is the first Hadoop release to depend on dnsjava 3.6.1. Any HBase artifact built against Hadoop 3.4.1 or later carries it. Verified by inspecting the published jars on Maven Central:
2.5.11-hadoop3through2.5.15-hadoop32.6.2-hadoop3through2.6.6-hadoop33.0.0-beta-2,3.0.02.5.10-hadoop3and earlier,3.0.0-beta-1and earlier2.5.xand2.6.x, and all2.4.xhbase-shaded-testing-utilis affected on the same builds.hbase-shaded-client-byo-hadoopandhbase-shaded-mapreducebundle no dnsjava, which is why switching to byo-hadoop is the downstream workaround.Reproduction
Any JDK 18+, no cluster needed, with an affected
hbase-shaded-clienton the classpath:A script that inspects a given jar and runs the lookup, with captured output on Java 11 and Java 21 against both a published jar and a patched build: https://gist.github.com/junegunn/5e51baf73f32ecbfcd4a9116b7df775a
A minimal project with only dnsjava 3.6.1 and maven-shade-plugin 3.6.0 reproduces it byte for byte, so nothing here is HBase specific. Shade 3.6.2, the latest release, produces the same broken output, so a plugin bump is not an alternative.
Fix
Extend the existing
dnsjava:dnsjavafilter inhbase-shaded/pom.xmlto drop the service file. The filter lives in the parent pluginManagement, so one edit covers every shaded artifact.The versioned entries under
META-INF/versions/18/are deliberately left in place. Removing the declaration is what fixes the failure, verified by rebuilding with only that exclusion. Those class entries carry relocated bytecode at an unrelocated path, so they cannot be loaded under either name, and excluding them would only drop a few KB of dead weight. The provider is opt-in behind theorg.dnsjava.spi.enablesystem property, so removing it costs nothing and all 315 relocated dnsjava classes stay.Marking the uber jar
Multi-Release: trueinstead does not work, since shade still leaves the versioned entry path unrelocated, and a relocated shaded client should not be installing a JVM wide DNS resolver anyway.The commit also adds a check to
ensure-jars-have-correct-contents.shin both invariants modules, failing the build when a shaded jar declares this SPI. Static rather than runtime, because precommit and nightly build on JDK 8, 11 and 17, where the SPI is never consulted and no runtime test can see the breakage. A general check, rejecting any service provider that is not loadable from its own jar, is left as future work.Unrelated but worth flagging: the surrounding content check in that script is a no-op on master and branch-3, from an
allowed_exprassignment bug in HBASE-29226, so it printsgrep: empty (sub)expression. Filing separately.Test result
Rebuilt
hbase-shaded-clientandhbase-shaded-testing-util: the service file is gone, all 315 relocated dnsjava classes are retained, andInetAddress.getByNamesucceeds on Java 21.mvn verifypasses on both invariants modules. The new check exits 1 on an affected published jar and 0 on the rebuilt artifacts.Context
Depended on by HBASE-29546.