Skip navigation

Netty 4.2 Migration Guide

Did you know this page is automatically generated from a Github Wiki page? You can improve it by yourself here!

Netty 4.2 Migration Guide

Netty 4.2 is largely backwards compatible with Netty 4.1, but there are a few choice compatibility breakages to be aware of, and a couple of new features worth knowing about.

From our (the Netty team) perspective, one of the biggest changes is that we are changing the minimum Java version requirement from Java 6 to Java 8. This upgrade is a big quality-of-life improvement for us, but it likely has no impact on anyone else because there are almost no regularly maintained Java projects left that still use Java versions older than Java 8.

Compatibility highlights

These are the most important compatibility breakages. The Netty team has done extensive validation testing of 4.2 in a number of large and high-profile projects, and these are the things that integrators are most likely to run into when upgrading their Netty dependencies from 4.1 to 4.2:

⚠️ For client TLS connections, we now enable hostname verification by default.

The SslContextBuilder.endpointIdentificationAlgorithm setting is now set to HTTPS by default, where in 4.1 it was null by default. Not doing hostname verification is obsolete and insecure practice from a more innocent time, that we haven't been able to change until now since suddenly enabling it could potentially break many systems.

This default can be overridden with a system property, to restore the Netty 4.1 behavior:

io.netty.handler.ssl.defaultEndpointVerificationAlgorithm=NONE

The purpose of this override is to aid systems with the Netty 4.2 migration. Systems that intentionally wish to disable endpoint identification should do so through the SslContextBuilder option.

⚠️ The adaptive memory allocator is now the default.

In Netty 4.1 the adaptive memory allocator was experimental. We have now made it the new default instead of the pooled allocator.

We believe that most workloads will observe reduced memory usage, with performance that is on par or slightly better than the pooled allocator. The adaptive allocator automatically tunes itself to perform well for the observed workload. It was also designed from the start to work well with virtual threads.

However, every application use their allocator in different ways, and stress them differently, so it is expected that the adaptive allocator will perform worse for some. Integrators who wish to keep using the pooled allocator like they did in Netty 4.1, can change the default allocator by setting this system property:

io.netty.allocator.type=pooled

⚠️ BouncyCastle upgrade.

We have updated our (still optional) BouncyCastle dependency. This is a breaking change because of how BouncyCastle versions their artifacts.

Our BouncyCastle dependencies have all changed from their *-jdk15on variants to their *-jdk18on variants.

This means that if you, for instance, are depending on both Netty and bcprov-jdk15on, then you will have to change which BouncyCastle artifact you depend on as part of your Netty 4.2 migration.

We have also upgraded the version we depend on from 1.69 to 1.80, which itself introduces compatibility breakages in their API.

⚠️ The netty-incubator-transport-io_uring module is no longer supported.

In Netty 4.2 we have graduated the io_uring transport from incubator, to a fully supported first-class transport module.

As part of this work, we have made numerous refactorings to the Netty transport internals that render the incubator version entirely incompatible. The good news is that netty-transport-native-io_uring is a much superior implementation thanks to these refactorings.

Integrators are encouraged to stop using the incubator module, and instead move to Netty 4.2 for its superior io_uring integration. Doing so will unfortunately require code changes. The following are things to watch out for:

  • The package name changes from io.netty.incubator.channel.uring to io.netty.channel.uring.
  • Class names are now prefixed IoUring instead of IOUring (note the lower-case ‘o’).
  • A number of io_uring channel options have changed.
  • IOUringEventLoopGroup does not exist anymore and is superseded by MultiThreadIoEventLoopGroup and IoUringIoHandler.
  • Usage of io_uring now requires Java9+.

Lesser compatibility changes

Netty 4.2 also includes a number of compatibility breakages that are less likely to cause problems, but needs to be mentioned regardless.

  • The protobuf-java dependency has received a major version bump from 2.6.1 to 3.25.5.
  • The netty-codec module has been split into a number of different sub-modules, which the netty-codec module then depends on. In other words, netty-codec is now multiple jar files instead of one.
  • We have dropped support for obsolete WebSocket draft specifications.
  • Dropped support for Jetty alpn/npn as ALPN is supported out of the box when using Java8.
  • The pipeline call-stack has been flattened, to reduce stack depths when processing messages through the pipeline. This may cause changes in behavior when messages are processed through the pipeline while the pipeline is concurrently modified, or when the pipeline makes use of child-executors.
  • The minimum required GLibC version is bumped from 2.12 (May 2010, e.g. CentOS 6) to 2.17 (December 2012, e.g. CentOS 7).
  • We are no longer testing our tcnative dynamic-linked OpenSSL integration with OpenSSL 1.0.1e (2013), and are now instead testing with OpenSSL 1.0.2k (2017).
  • Switched from automatic to real modules for JPMS.

The complete and exhaustive list of API breakages has been compiled by RevAPI: https://github.com/netty/netty/blob/3ca17a96cf84cbcb08776d3731b222b82814ead7/pom.xml#L1271-L7794

New best practices

Netty 4.2 introduces some new APIs, and deprecates some old APIs. As part of your migration to Netty 4.2, we encourage you to look through your code base for opportunities to clean up any use of deprecated APIs.

✅ IoHandlerFactories for EventLoopGroups

All transport-specific event loop groups, such as NioEventLoopGroup, have been deprecated.

Integrators should now instead pass a transport-specific IoHandlerFactory to a MultiThreadedEventLoopGroup constructor.

For example, stop doing this

EventLoopGroup group = new NioEventLoopGroup(); // ❌

and instead start doing this

EventLoopGroup group = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory()); // ✅

There is a static newFactory method for each of our transports:

  • NioIoHandler.newFactory()
  • EpollIoHandler.newFactory()
  • KQueueIoHandler.newFactory()
  • IoUringIoHandler.newFactory()
  • LocalIoHandler.newFactory()

Note that you must still configure the relevant channel or channel factory in your Bootstrap or ServerBootstrap instances.

✅ Extensibility of MultiThreadIoEventLoopGroup and SingleThreadIoEventLoop

The MultiThreadIoEventLoopGroup and SingleThreadIoEventLoop classes provide various methods that can be overridden by the user, and provide the ability to:

  • Get a count of registered channels / handles
  • Understand how long the IO processing vs task processing took
  • Get how many channels / handles were processed per loop run
  • Customize / decorate promises

Furthermore, it is now possible to register other things than Channels (as long as the correct IoHandle type is implemented), which provides a lot of possibilites to re-use netty components and also add support for other IoHandle implementations which does not exists as of today. For example, this could be used to implement file IO with io_uring.

✅ Use netty-pkitesting instead of SelfSignedCertificate

Netty 4.1 includes a SelfSignedCertificate class, which we use for testing our TLS implementation. This was not intended to be used as widely as it has ended up, and it suffers from a number of API decisions that make it a poor fit as a general purpose PKI and TLS testing tool.

In Netty 4.2 we are introducing a new module, netty-pkitesting, which includes a CertificateBuilder class. The CertificateBuilder is designed to allow integrators to test all sorts of PKI and TLS scenarios.

You can make self-signed certificates like before, or you can make proper CA, issuer, leaf certificate chains. The CertificateBuilder produces X509Bundle objects, which contain both certificate chains and the corresponding private key, and the bundles are created entirely in-memory without writing any files. If you need files for certificates, keys, or key stores, then the bundle objects include a number of convenient methods for creating temporary files for these.

The netty-pkitesting module also includes a simple Certificate Revocation List server, so you can test scenarios where certificates are revoked.

Last retrieved on 03-Apr-2025