Skip to content

Only use MemorySegments on Java 25+#15338

Merged
normanmaurer merged 13 commits intonetty:4.2from
chrisvest:4.2-memseg-jdk25
Jun 13, 2025
Merged

Only use MemorySegments on Java 25+#15338
normanmaurer merged 13 commits intonetty:4.2from
chrisvest:4.2-memseg-jdk25

Conversation

@chrisvest
Copy link
Copy Markdown
Member

@chrisvest chrisvest commented Jun 10, 2025

Motivation:
We wish to use memory segments for managing direct memory, as Unsafe is going away. However, we cannot use this feature unless the application is running on Java 25 or better due to the following JDK bugs:

In Netty, we can work around those bugs.
However, our downstream users are also getting ByteBuffers out of our ByteBuf instances, and making their own calls into the JDK APIs, and can thus also run into these bugs. Effectively, this breaks their systems when we enable memory segments on Java 24.

Modification:
Change CleanerJava24 to CleanerJava25, and only enable it on Java 25+.

Add a build to the PR matrix for Java 25 Early Access.

Add a nightly workflow that checks the latest Java 25 Early Access build version, which will fail if a new version is released. This workflow will help us stay up to date on the latest Java 25 Early Access version. We can remove it or disable it once Java 25 is released. Maybe we want something similar for Java 26 and so on, in the future.

Result:
We only use memory segments on Java versions where they don't run into buggy interactions.

Fixes #15324

@wendigo
Copy link
Copy Markdown

wendigo commented Jun 10, 2025

Thanks @chrisvest !

@chrisvest
Copy link
Copy Markdown
Member Author

JBoss marshalling is getting caught with its fingers in the reflection jar by JDK 25 EA.

2025-06-10T20:03:44.6931030Z [ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.022 s <<< FAILURE! -- in io.netty.testsuite_jpms.test.CodecMarshallingTest
2025-06-10T20:03:44.6933438Z [ERROR] io.netty.testsuite_jpms.test.CodecMarshallingTest.smokeTest -- Time elapsed: 0.017 s <<< ERROR!
2025-06-10T20:03:44.6935510Z java.lang.ExceptionInInitializerError
2025-06-10T20:03:44.6936471Z 	at io.netty.testsuite_jpms.test/io.netty.testsuite_jpms.test.CodecMarshallingTest.smokeTest(CodecMarshallingTest.java:41)
2025-06-10T20:03:44.6937529Z 	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
2025-06-10T20:03:44.6938246Z 	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
2025-06-10T20:03:44.6939148Z 	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
2025-06-10T20:03:44.6940612Z Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make java.io.OptionalDataException(boolean) accessible: module java.base does not "opens java.io" to module jboss.marshalling
2025-06-10T20:03:44.6942614Z 	at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:353)
2025-06-10T20:03:44.6944027Z 	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:329)
2025-06-10T20:03:44.6945198Z 	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:277)
2025-06-10T20:03:44.6946301Z 	at java.base/java.lang.reflect.Constructor.checkCanSetAccessible(Constructor.java:192)
2025-06-10T20:03:44.6947265Z 	at java.base/java.lang.reflect.Constructor.setAccessible(Constructor.java:185)
2025-06-10T20:03:44.6948469Z 	at jboss.marshalling@1.4.11.Final/org.jboss.marshalling.Marshalling$OptionalDataExceptionCreateAction$1.run(Marshalling.java:394)
2025-06-10T20:03:44.6950422Z 	at jboss.marshalling@1.4.11.Final/org.jboss.marshalling.Marshalling$OptionalDataExceptionCreateAction$1.run(Marshalling.java:390)
2025-06-10T20:03:44.6951782Z 	at java.base/java.security.AccessController.doPrivileged(AccessController.java:74)
2025-06-10T20:03:44.6953052Z 	at jboss.marshalling@1.4.11.Final/org.jboss.marshalling.Marshalling$OptionalDataExceptionCreateAction.<init>(Marshalling.java:390)
2025-06-10T20:03:44.6954594Z 	at jboss.marshalling@1.4.11.Final/org.jboss.marshalling.Marshalling$OptionalDataExceptionCreateAction.<init>(Marshalling.java:385)
2025-06-10T20:03:44.6955882Z 	at jboss.marshalling@1.4.11.Final/org.jboss.marshalling.Marshalling.<clinit>(Marshalling.java:383)
2025-06-10T20:03:44.6956636Z 	... 4 more

I'll try upgrading it from 2.0.5 to 2.2.3, but I'm not sure that'll do much. I think it needs to catch java.lang.reflect.InaccessibleObjectException in addition to the set it currently looks for.
FYI @dmlloyd

@dmlloyd
Copy link
Copy Markdown

dmlloyd commented Jun 10, 2025

JBoss marshalling is getting caught with its fingers in the reflection jar by JDK 25 EA.

I'll try upgrading it from 2.0.5 to 2.2.3, but I'm not sure that'll do much. I think it needs to catch java.lang.reflect.InaccessibleObjectException in addition to the set it currently looks for. FYI @dmlloyd

This was indeed fixed to use permitted APIs since 2.2.0, so upgrading should get you around this problem.

@chrisvest
Copy link
Copy Markdown
Member Author

Thanks, David!

Motivation:
We wish to use memory segments for managing direct memory, as Unsafe is going away.
However, we cannot use this feature unless the application is running on Java 25 or better due to the following JDK bugs:

- https://bugs.openjdk.org/browse/JDK-8357145
- https://bugs.openjdk.org/browse/JDK-8357268

In Netty, we can work around those bugs.
However, our downstream users are also getting `ByteBuffers` out of our `ByteBuf` instances, and making their own calls into the JDK APIs, and can thus also run into these bugs.
Effectively, this breaks their systems when we enable memory segments on Java 24.

Modification:
Change CleanerJava24 to CleanerJava25, and only enable it on Java 25+.

Add a build to the PR matrix for Java 25 Early Access.

Add a nightly workflow that checks the latest Java 25 Early Access build version, which will fail if a new version is released.
This workflow will help us stay up to date on the latest Java 25 Early Access version.
We can remove it or disable it once Java 25 is released.
Maybe we want something similar for Java 26 and so on, in the future.

Result:
We only use memory segments on Java versions where they don't run into buggy interactions.

Fixes netty#15324
This changed in 2.2.0, presumably.
@chrisvest
Copy link
Copy Markdown
Member Author

Rather mysteriously, compilation fails in the testsuite-jpms module because the MarshallerFactory cannot be found, despite the JBoss Marshalling jar being on the javac module path when compiling tests.

@chrisvest
Copy link
Copy Markdown
Member Author

The error message from javac was very confusing in this case. But somehow codec-marshalling was compiled to require the jboss.marshalling module, while the testsuite-jpms was requiring org.jboss.marshalling. The javac error only said that a class wasn't available, but made no mention about what modules it was working with or expecting the class from.

I think we have to bump our marshalling dependency generally, and not just during compilation. Otherwise downstream users will run into this error, but in reverse.

@normanmaurer
Copy link
Copy Markdown
Member

@chrisvest you also need to add a profile for blockhound that will add -XX:+AllowRedefinitionToAddDeleteMethods on JDK25

@chrisvest
Copy link
Copy Markdown
Member Author

@normanmaurer We're gonna have to skip blockhound entirely for Java 25 EA, at least for the current build 26. I think there's a JDK bug preventing it from working.
FYI @violetagg

@derklaro
Copy link
Copy Markdown
Contributor

@chrisvest judging from the failing build output I'd suspect that you need to upgrade blockhound to at least 1.0.12.RELEASE as this version includes an updated bytebuddy version which itself includes an asm version with java 25 support. Another option would be to include https://github.com/raphw/asm-jdk-bridge to use the jdk classfile api when asm is unavailable (and it's supported) - don't know if that's actually needed (nor if it's a good idea given that there is no release yet).

@normanmaurer
Copy link
Copy Markdown
Member

Let's merge this for now... @derklaro we can open a new PR and try your suggestion there.

@normanmaurer normanmaurer merged commit a919dd3 into netty:4.2 Jun 13, 2025
28 of 29 checks passed
@chrisvest chrisvest deleted the 4.2-memseg-jdk25 branch June 13, 2025 17:34
@chrisvest
Copy link
Copy Markdown
Member Author

Thanks for taking care of this. Hadn't considered there was a new version of Blockhound.

dongjoon-hyun added a commit to apache/spark-kubernetes-operator that referenced this pull request Mar 26, 2026
…ing to Netty change

### What changes were proposed in this pull request?

This PR removes `-Dio.netty.noUnsafe=true` from the default JVM args in `values.yaml`.

### Why are the changes needed?

Netty 4.2.2+ have a correct implementation instead of `Unsafe` usage for Java 25+ like the following instead of the legacy `Unsafe` operation.

- netty/netty#15231
- netty/netty#15338

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

Pass the CIs with the existing tests.

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Code (claude-4-opus)

Closes #593 from dongjoon-hyun/SPARK-56229.

Authored-by: Dongjoon Hyun <dongjoon@apache.org>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
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.

Cassandra client fails with Netty 4.2.2

5 participants