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
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:
flush() were replaced by
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
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
Here are some other changes that might interest you:
EmbeddedMessageChannelhas been merged into
Channel.isWritable()in 3 has been brought back.
ChannelInboundHandler.channelWritabilityChanges()event which is similar to
- 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,
RecvByteBufAllocatorhas been added as a configuration property.
- It is similar to
- Some existing configuration properties such as
DatagramChannelConfig.receivePacketSizeis gone now.
- It is similar to
Other noteworthy changes
io.netty.buffer.ReferenceCountedhas been moved to
- Resource leak detection has been turned on by default.
PooledByteBufAllocatorproduces zero garbage now if resource leak detection is turned off by
- The cancellation of
Promiseworks as expected now. (#1432)
GlobalEventExecutorhas 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
- Message type hierarchy of SPDY has been revised. (#1418)
Visit here for the complete list of the changes.
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.