Skip navigation

Netty 4.0.0.Final released

After more than a year of journey for an even better networking application framework, we finally released Netty 4.0.0.Final yesterday, which is the official stable version with the vast number of changes.

I'd like to thank everyone who was involved in the development of this monumental release. In spite of many backward-incompatible changes between releases, which sometimes might have looked fickle, the early adopters were extremely patient and helpful to drive us in a right direction. Some of them even tested the unstable releases in their production environment, which was crucial to our decision to release the final version. If this release is unusually rock-solid and high-performing, it's thanks to all of those great people for sure.

What would be waiting in front of us? We are excited that we are going to make the version 4 much more stable, to improve documentation, to give advise to help those who migrate 3.x-based apps to 4, and to make Netty faster than ever. I hope you become a part of all these efforts.

Changes since 4.0.0.CR9

Removal of MessageList

I must admit MesageList was pain in the butt. Instead of forcing a handler always loop over the list of messages, I split ChannelInboundHandler.messageReceived(ctx, list) into two event handler methods:

  • channelRead(ctx, msg)
  • channelReadComplete(ctx)

When Netty reads one or more messages, channelRead() event is triggered for each message. Once the current read operation is finished, channelReadComplete() is triggered to tell the handler that the last channelRead() was the last message in the current batch.

Similarly, for outbound, write(ctx, list) has been split into the following:

  • write(ctx, msg, promise)
  • flush(ctx)

Instead of writing a list of messages with a promise, a user is now supposed to call write(msg) multiple times and then call flush() to actually flush the buffered messages.

Please note that flush() doesn't have a promise with it. You must write something to get notified on completion. As you did in 3.x, the trick of writing an empty buffer works here, too.

Related miscellaneous changes

  • ChannelInboundHandler.channelReadSuspended() has been replaced by channelReadComplete() introduced above, because they are essentially same.
  • Because MessageList is gone, codec framework now uses List<Object> instead of MessageList as an output parameter.

Other changes

  • UnpooledByteBufAllocator is the default allocator. We suspect there might be a leak in the PooledByteBufAllocator. Until the investigation is complete and any bugs found are fixed, we are defaulting to UnpooledByteBufAllocator.
  • ByteBuf is now an abstract class rather than an interface. I found that converting ByteBuf from an interface to an abstract class gives the nice performance boost of around 5%. Hence ByteBuf was converted to an abstract class.
  • Channel.id() has been removed. It was practically impossible to generate a unique ID of a Channel with the new API because there is no way to manage the global map of the taken IDs

Visit here for the complete list of the changes.