Skip to content

[improve][build] Set --enable-native-access=ALL-UNNAMED for test JVMs on Java 24+ - #26367

Merged
nodece merged 1 commit into
apache:masterfrom
lhotari:lh-fix-test-enable-native-access
Aug 19, 2026
Merged

[improve][build] Set --enable-native-access=ALL-UNNAMED for test JVMs on Java 24+#26367
nodece merged 1 commit into
apache:masterfrom
lhotari:lh-fix-test-enable-native-access

Conversation

@lhotari

@lhotari lhotari commented Aug 18, 2026

Copy link
Copy Markdown
Member

Motivation

Netty loads its native libraries (epoll, io_uring, tcnative) through
java.lang.System::loadLibrary, which became a restricted method in Java 24. Any test JVM that
touches a Netty native transport therefore prints to stderr:

WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::loadLibrary has been called by io.netty.util.internal.NativeLibraryUtil
         in an unnamed module
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

Pulsar already runs CI on JDK 25, so this is noise on every affected test JVM. It also
interferes with tests that assert a process wrote nothing to stderr, and, as the warning says,
restricted methods will eventually be blocked rather than warned about.

bin/pulsar already passes --enable-native-access=ALL-UNNAMED for the server, and #26365 adds
it to the CLI scripts. This PR does the same for the test JVMs.

Modifications

In build-logic/conventions/src/main/kotlin/pulsar.java-conventions.gradle.kts:

// Effective Java major version used to run tests: the -PtestJavaVersion override when set,
// otherwise the JVM running Gradle.
val testJavaMajorVersion = testJavaVersion.orNull ?: JavaVersion.current().majorVersion.toInt()

and, inside tasks.withType<Test>().configureEach:

if (testJavaMajorVersion >= 24) {
    jvmArgs("--enable-native-access=ALL-UNNAMED")
}

The version gate matters because the option is not accepted by older JVMs, and tests can be run
on an older JDK via -PtestJavaVersion. The effective version therefore honours that toolchain
override when present and falls back to the JVM running Gradle, so the gate is correct in both
cases.

Verifying this change

  • Make sure that the change passes the CI checks.

This change is a trivial rework / code cleanup without any test coverage.

Verified locally that the conditional actually takes effect, in both directions, by inspecting
the test worker command line with --rerun-tasks -i:

  • with the threshold temporarily lowered to 21 on a Java 21 JVM, --enable-native-access=ALL-UNNAMED
    appears in the spawned test JVM arguments;
  • with the threshold at 24 on the same Java 21 JVM, it does not appear.

Also ran ./gradlew :buildtools:compileJava to confirm the convention plugin still compiles, and
a targeted test to confirm test execution is unaffected.

Does this pull request potentially affect one of the following parts:

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

… on Java 24+

Netty loads its native libraries (epoll, io_uring, tcnative) through
java.lang.System::loadLibrary, which is a restricted method as of Java 24. Every test JVM
that touches a Netty native transport therefore prints a multi-line warning to stderr:

  WARNING: A restricted method in java.lang.System has been called
  WARNING: java.lang.System::loadLibrary has been called by
           io.netty.util.internal.NativeLibraryUtil in an unnamed module
  WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
  WARNING: Restricted methods will be blocked in a future release unless native access is enabled

That is noise in test output, it interferes with assertions on empty stderr, and the JDK
will block restricted methods outright in a future release.

The flag is added to the Test task JVM arguments only when the Java version used to run the
tests is 24 or later, since the option is not accepted by older JVMs. The effective version
is the -PtestJavaVersion toolchain override when set, and otherwise the JVM running Gradle,
so the gate is correct for both.

This mirrors what bin/pulsar already does for the server and what the CLI scripts do for
pulsar-admin, pulsar-client, pulsar-shell and pulsar-perf.

Assisted-by: Claude Code (Opus 5)
@lhotari
lhotari requested a review from merlimat August 18, 2026 07:56
@lhotari lhotari added the area/dependency Pull requests that update a dependency file label Aug 18, 2026
@lhotari lhotari added this to the 5.0.0-M2 milestone Aug 18, 2026
@lhotari lhotari removed the area/dependency Pull requests that update a dependency file label Aug 18, 2026

@void-ptr974 void-ptr974 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nodece
nodece merged commit 81936d5 into apache:master Aug 19, 2026
81 of 83 checks passed
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.

3 participants