Skip navigation

Netty 4.0.0.CR5 released with new-new API

You might already have seen we tagged 4.0.0.CR5 (and CR4) recently and wondered why no release announcement was coming along. Here's the announcement finally with choke full of changes.

This release is different from others because of its huge change in the API. I'd like to apologize for the broken backward compatibility again and explain why this change was required. Also, please read the revised user guide and the complete list of the changes in 4.

Why breakage again?

The API changes made so far turned out to increase the memory footprint and consumption while our intention was actually decreasing them.

Memory consumption issue

When there are many connections which does not exchange data frequently, the old Netty 4 API spent a lot more memory than 3 because it always allocates per-handler buffer for each connection unless otherwise explicitly stated by a user. In a usual real world load, a client doesn't always send requests without pausing, so the idea of having a buffer whose life cycle if bound to the life cycle of a connection didn't work as expected.

Memory footprint issue

The old Netty 4 API decreased overall memory footprint by a great deal in many cases. It was mainly because the old Netty 4 API did not allocate a new buffer and event object for each read. Instead, it created a new buffer for each handler in a pipeline. This works pretty well as long as the number of handlers in a pipeline is only a few. However, for a highly modular application with many handlers which handles connections which lasts for relatively short period, it actually makes the memory footprint issue much worse.

How did we fix them this time?

All in all, this is about retaining all the good changes we made in 4 so far such as better thread model and going back to the way how we dealt with message events in 3. The distinction of MessageBuf and ByteBuf is now gone, and Netty simply treats a ByteBuf as a message just like Netty 3 did. A ByteBuf is not allocated per handler anymore.

To follow the change, the type hierarchy of ChannelHandler became very similar to that of Netty 3:

ChannelHandler type hierarchy diagram

Consequently, inboundBufferUpdated() and flush() were replaced by messageReceived() and write() (similar to filterWrite() in 3) respectively.

Another change to note is that MessageBuf is gone and a new type called MessageList is used as a parameter of messageReceived() and write(). It is basically a light-weight container of multiple messages.

Due to the changes above, some handler implementations have no value anymore and thus were removed: ByteToByteEncoder/Decoder/Codec. Please use MessageToByteEncoder<ByteBuf>, ByteToMessageDecoder<ByteBuf>, and ByteToMessageCodec<ByteBuf> instead.

Here are some other changes that might interest you:

  • EmbeddedByteChannel and EmbeddedMessageChannel has been merged into EmbeddedChannel.
  • Channel.isWritable() in 3 has been brought back.
    • Added ChannelInboundHandler.channelWritabilityChanges() event which is similar to channelInterestOpsChanged() in 3.
  • Because a handler does not have its own buffer, Netty has to allocate a new buffer whenever it reads something. To get the optimal size of the new buffer, RecvByteBufAllocator has been added as a configuration property.
    • It is similar to ReceiveBufferSizePredictor.
    • Some existing configuration properties such as DatagramChannelConfig.receivePacketSize is gone now.

Other noteworthy changes

  • io.netty.buffer.ReferenceCounted has been moved to io.netty.util. (#1441)
  • Resource leak detection has been turned on by default.
  • The ByteBuf created by PooledByteBufAllocator produces zero garbage now if resource leak detection is turned off by -Dio.netty.noResourceLeakDetection JVM flag.
  • The cancellation of Future and Promise works as expected now. (#1432)
  • GlobalEventExecutor has been added to allow a user to execute an arbitrary task from a global singleton thread. (#1389)
  • Bootstrap.group() getter method has been added for easier access to its underlying EventLoopGroup. (#1425)
  • Message type hierarchy of SPDY has been revised. (#1418)

Visit here for the complete list of the changes.

Acknowledgement

Every idea and bug-report counts and so we thought it is worth mentioning those who helped in this area. Please report an unintended omission.

Last but not least, this change would have been impossible without @normanmaurer's help. He fixed, ported, and improved many parts of my changes.