Skip to content

Ship native-image metadata for kqueue (macOS/BSD) (#17112) - #17113

Open
emilienbev wants to merge 1 commit into
netty:4.2from
emilienbev:fix-17112
Open

Ship native-image metadata for kqueue (macOS/BSD) (#17112)#17113
emilienbev wants to merge 1 commit into
netty:4.2from
emilienbev:fix-17112

Conversation

@emilienbev

@emilienbev emilienbev commented Jul 21, 2026

Copy link
Copy Markdown

Motivation

The netty-transport-classes-kqueue (macOS) module doesn't include GraalVM native-image metadata in META-INF/native-image, while its Linux counterpart netty-transport-classes-epoll does.

Because of this the kqueue classes default to build-time class initialization under native-image, meaning KQueue.isAvailable() == true is baked into the image heap at build-time, which crashes applications at runtime with an UnsatisfiedLinkError when the package isn't available.

Modifications

Added a META-INF/native-image directory for kqueue, similar to epoll:

  • native-image.properties: added --initialize-at-run-time=io.netty.channel.kqueue,io.netty.channel.unix.Limits,io.netty.channel.unix.IovArray,io.netty.channel.unix.Errors (so KQueue.isAvailable() is evaluated at runtime)
  • resource-config.json: added the kqueue native library (.libnetty_transport_native_kqueue_..jnilib).
  • reflect-config.json / jni-config.json: added reflection/JNI registrations, guarded by typeReachable: io.netty.channel.kqueue.Native.

The metadata mirrors epoll's but is adjusted where the two transports differ:

  • kqueue has an extra channel KQueueDomainDatagramChannel registered in this PR.
  • epoll registers NativeDatagramPacketArray$NativeDatagramPacket for JNI, but kqueue
    has no such class (it receives datagrams via DatagramSocketAddress and
    DomainDatagramSocketAddress, which are both registered, so nothing's needed here)

Result

Fixes #17112

@emilienbev emilienbev changed the title Ship native-image metadata for kqueue so KQueue.isAvailable() is evaluated at runtime (#17112) Ship native-image metadata for kqueue (macOS/BSD) (#17112) Jul 22, 2026
@emilienbev

Copy link
Copy Markdown
Author

@franz1981 You might be the right reviewer for this one?

@normanmaurer

Copy link
Copy Markdown
Member

/cc @yawkat @vietj @violetagg

@chrisvest

Copy link
Copy Markdown
Member

Has couchbase signed a corp CLA or does Emilien need to sign an ICLA?

@emilienbev

emilienbev commented Jul 22, 2026

Copy link
Copy Markdown
Author

@chrisvest apologies I hadn't done so, I just signed an individual one and represent myself here.

@chrisvest chrisvest left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM but I'll wait to hear from the others before merging.

@violetagg

violetagg commented Jul 23, 2026

Copy link
Copy Markdown
Member

GraalVM team automated the generation of the reachability metadata. Do we want to handle it manually?
https://github.com/oracle/graalvm-reachability-metadata/tree/master/metadata/io.netty

for example oracle/graalvm-reachability-metadata#9073

@emilienbev

emilienbev commented Jul 24, 2026

Copy link
Copy Markdown
Author

Good point @violetagg, I think this is your call on direction, although it doesn't have to be either/or.

I feel stronger towards Netty owning its metadata because adding it here stays consistent with how Netty already handles other parts of the code (there's in-jar metadata for epoll, io_uring, buffer, common and friends, and this PR really just mirrors the epoll setup for kqueue), and I noted the testsuite-native-image runs with metadataRepository disabled, so in-jar configuration seems expected to stand on its own.

Also the GraalVM repo handles reachability metadata, but it won't cover some gaps (here, the native-image.properties), which then either need downstream users to fix individually, or to be handled upstream so it's shared for everyone. Per the docs:

No build-time-initialization tweaks. Metadata bundles must not ship native-image.properties or any other directive that moves class execution into the image builder

The same reasoning also applies to the OpenSSL PRs #17131 and netty/netty-tcnative#992 (but I don't mean to drift the conversation here).
I'd lean towards native-image configuration living with the JAR it targets, but let me know what you think.

…uated at runtime (netty#17112)

Signed-off-by: Emilien Bevierre <emilien.bevierre@couchbase.com>
@violetagg

Copy link
Copy Markdown
Member

I have a few concerns about hosting it here: it currently lacks automation, tests, and documented knowledge. oracle/graalvm-reachability-metadata already has all three in place, which is worth taking into consideration.

@emilienbev

Copy link
Copy Markdown
Author

I can tighten the PR to just the parts the graalvm-reachability repo isn't meant for, i.e. keep the native-image.properties and the resource-config.json that embeds the platform-locked lib in thsi PR for consistency with epoll/io_uring, and drop the reflect/jni parts if you'd rather those come from the graalvm repo.

Let me know which you prefer and I'll update the PR.

@violetagg

Copy link
Copy Markdown
Member

@emilienbev I think when one wants to use the reachability metadata, all metadata provided by the library is ignored.

@testlens-app

testlens-app Bot commented Jul 27, 2026

Copy link
Copy Markdown

🚨 TestLens detected 1 failed test 🚨

Here is what you can do:

  1. Inspect the test failures carefully.
  2. If you are convinced that some of the tests are flaky, you can mute them below.
  3. Finally, trigger a rerun by checking the rerun checkbox.

Test Summary

Build PR / macos-aarch64-java11-boringssl build > Netty/Transport/Native/KQueue

Test Runs Flakiness
KQueueETSocketHalfClosedTest > testAllDataReadClosure(TestInfo) 🚫 ❌ 3% 🟡

🏷️ Commit: d9dc03e
▶️ Tests: 28584 executed
⚪️ Checks: 18/18 completed

Test Failures

KQueueETSocketHalfClosedTest > testAllDataReadClosure(TestInfo) (Netty/Transport/Native/KQueue in Build PR / macos-aarch64-java11-boringssl build)
java.util.concurrent.TimeoutException: testAllDataReadClosure(org.junit.jupiter.api.TestInfo) timed out after 20000 milliseconds
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	Suppressed: java.lang.InterruptedException
		at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1040)
		at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1345)
		at java.base/java.util.concurrent.CountDownLatch.await(CountDownLatch.java:232)
		at io.netty.testsuite.transport.socket.SocketHalfClosedTest.testAllDataReadClosure(SocketHalfClosedTest.java:779)
		at io.netty.testsuite.transport.socket.SocketHalfClosedTest.testAllDataReadClosure(SocketHalfClosedTest.java:685)
		at io.netty.testsuite.transport.socket.SocketHalfClosedTest$16.run(SocketHalfClosedTest.java:679)
		at io.netty.testsuite.transport.socket.SocketHalfClosedTest$16.run(SocketHalfClosedTest.java:676)
		at io.netty.testsuite.transport.AbstractComboTestsuiteTest.run(AbstractComboTestsuiteTest.java:52)
		at io.netty.testsuite.transport.socket.SocketHalfClosedTest.testAllDataReadClosure(SocketHalfClosedTest.java:676)
		at java.base/java.lang.reflect.Method.invoke(Method.java:566)
		... 2 more

Muted Tests

Select tests to mute in this pull request:

  • KQueueETSocketHalfClosedTest > testAllDataReadClosure(TestInfo)

Reuse successful test results:

  • ♻️ Only rerun the tests that failed or were muted before

Click the checkbox to trigger a rerun:

  • Rerun jobs

Learn more about TestLens at testlens.app.

@emilienbev

emilienbev commented Jul 29, 2026

Copy link
Copy Markdown
Author

@violetagg Yes. In our case we don't consume the reachability repo, though we certainly could source from it at build time. Either way we'd still need the run-time inits from native-image.properties which the graalvm repo can't provide, so that has to live either here in the source or be added individually downstream.

For us this particular metadata isn't a big deal, but more generally having native-image metadata ship with each dependency's source spares us downstream projects from hand-maintaining and patching it ourself for every dependency.

I'm happy to drop the reachability metadata from this PR if the preferred direction is to leave that to the graalvm repo. My reading of the existing epoll/io_uring etc... metadata, and metadataRepository being disabled in the tests was that Netty intends to ship its native-image metadata with the source directly, but I'm glad to go with whatever you prefer going forward.

Whichever way you decide, the same applies to the two OpenSSL PRs (#17131 and netty/netty-tcnative#992), so I would adapt those to match.

@normanmaurer

Copy link
Copy Markdown
Member

@violetagg @yawkat @franz1981 thoughts ?

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.

netty-transport-classes-kqueue is missing GraalVM native-image metadata

4 participants