Repository navigation
Use sun.misc.Unsafe only where Netty does - #53
Merged
Merged
Conversation
Since JDK 24 the first call to a memory-access method of sun.misc.Unsafe prints a warning that names the caller (JEP 498). LightProtoCodec looks Unsafe up in its static initializer, so it prints that warning whenever Netty doesn't use Unsafe itself: by default from Netty 4.2 on Java 25, and with -Dio.netty.noUnsafe=true or --sun-misc-unsafe-memory-access set to anything but allow. Where Netty uses it, Netty has printed the warning already, and the JVM prints it only once. The codec now looks Unsafe up only when PlatformDependent.hasUnsafe() is true. Where it is, nothing else changes. Where it isn't, the paths without Unsafe are taken, and two of them no longer allocate a temporary array per ASCII string: arrays are written with String.getBytes(int, int, byte[], int), and NIO views with one put per char, which was faster than staging the bytes at every length measured. Removing Unsafe outright was measured and rejected: the JDK can't build a String around an existing array, or read a String's bytes, without a copy, so string reads from direct buffers, string-dense serialization and NIO-view writes of strings got 7-67% slower on JDK 26.
2 of 11 tasks
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.
Problem
Since JDK 24, the first call to one of
sun.misc.Unsafe's memory-access methods prints a warning naming the caller (JEP 498).LightProtoCodeclooks Unsafe up in its static initializer. An application whose Netty doesn't use Unsafe therefore gets that warning from LightProto:io.netty.noUnsafe=trueis the default.-Dio.netty.noUnsafe=true.--sun-misc-unsafe-memory-access=warn|deny, which Netty 4.1.131 also honors.Where Netty uses Unsafe (Netty 4.1 by default), Netty's own calls have printed the warning already, and the JVM prints it only once.
Example
Parsing or writing any LightProto message with
-Dio.netty.noUnsafe=trueon JDK 26:The call comes from the codec's static initializer:
Change
The codec looks Unsafe up only when Netty uses it (the
tryblock is only re-indented):Where Netty uses Unsafe, nothing else changes. Where it doesn't, the paths without Unsafe are taken. Two of them no longer allocate a temporary array per ASCII string:
Both replace
getBytes(ISO_8859_1)copies and were faster at every length measured, from 3 to 2000 chars. The NIO writer is allocation-free, soNioWriteTest's allocation check no longer skips-XX:-CompactStrings.Why not remove Unsafe
The JDK has no public way to build a String around an existing
byte[], or to read a String's bytes, without copying them. JDK 26'sMemorySegment.getString/setStringonly handle NUL-terminated strings. Without Unsafe, the string paths got slower.Measured on JDK 26 with interleaved A/B runs (4-6 forks per variant), as the change in time per op, where positive is slower:
With Netty's Unsafe off (
-Dio.netty.noUnsafe=true), this PR trades the warning for the paths without Unsafe:Testing
NoUnsafeTeststarts a JVM with-Dio.netty.noUnsafe=true --sun-misc-unsafe-memory-access=warn. It round-trips strings through the heap, direct, NIO-view and gRPC-view paths and asserts that no Unsafe warning is printed. It fails on master with the warning above. It needs JDK 23+ for the flag, so CI's JDK 17 skips it.mvn verifyruns 584 tests in each of the two surefire executions (default and-XX:-CompactStrings), all passing.