Java 24 and sun.misc.Unsafe
Java 24 integrated JEP 498 and started printing warnings to the console, when sun.misc.Unsafe
memory-access methods are first used.
Netty has historically been relying on these methods to more efficiently work with native (off-heap) memory. This means applications that use Netty, and run on Java 24 or greater, may see these warnings.
To avoid these warnings being printed when using Netty 4.1, users have to explicitly allow Unsafe memory access using the following command line argument for the JVM:
--sun-misc-unsafe-memory-access=allow
Netty 4.1.120 and 4.1.121 disabled its use of sun.misc.Unsafe
by default when running on Java 24 or greater (PR #14943), to avoid these warnings showing up for our users.
This changed default is reverted in Netty 4.1.122 (PR #15296), so the behavior is restored to what it was in Netty 4.1.119.
The reason we decided to revert the change in behavior is that 1) the performance regression was greater than anticipated, and 2) making use of JNI (such as when using our native transports or native TLS implementation) produced a similar warning, but with no way for us to work around it in the Netty 4.x versions.
Netty 4.2.0 and 4.2.1 take no special precautions, and produce warnings the same as Netty 4.1 (excluding 4.1.120 and 4.1.121) does.
Netty 4.2.2 adds support for using MemorySegment
APIs to avoid relying on Unsafe
(PR #15231).
Netty and its native transports need native (off-heap) memory to move data faster to and from the operating system, i.e. without copying data into and out of the heap as well.
To effectively work with native memory, Netty needs a way to not only allocate memory, but also deallocate it as soon as it's done using it. Netty needs Unsafe
to access the cleaner instance inside the direct ByteBuffers
. The cleaner is the mechanism used to deallocate the memory in direct ByteBuffer
instances.
When Unsafe
is not available to Netty, then the ByteBuffer
cleaner is also not available to Netty, and it instead has to rely on the garbage collector for releasing the memory.
The garbage collector runs in response to heap memory pressure, but direct buffers do not produce much memory pressure on the heap. This causes native memory to be released after a greater delay than strictly necessary, which in turn increases memory usage. The JDK attempts to work around this by occasionally running the garbage collector explicitly when allocating new direct ByteBuffer
instances, and then sleeping for 100 milliseconeds.
This behavior, the increased explicit GC and the 100 milliseconds sleep, is unacceptable to Netty. We cannot accept sleeping or any other blocking operation in the event loop thread.
For this reason, Netty will use heap buffers by default when the direct ByteBuffer
cleaner is not available.
As a consequence, heap usage can be greatly increased on systems where Unsafe
is not available, and the time and CPU resources spent on garbage collection likewise increase, with reduced system-wide performance as a result.