ByteBuf Module provides memory-efficient, recyclable byte buffers.
You can add ByteBuf module to your project by inserting dependency in
The main components of the module are:
An extremely lightweight and efficient implementation compared to the Java NIO ByteBuffer. There are no direct buffers, which simplifies and improves ByteBuf performance.
ByteBuf is similar to a FIFO byte queue and has two positions: head and tail. When you write data to your ByteBuf, its tail increases by the amount of bytes written. Similarly, when you read data from your ByteBuf, its head increases by the amount of bytes read. You can read bytes from ByteBuf only when tail is greater then head. Also, you can write bytes to ByteBuf until tail doesn’t exceed the length of the wrapped array. In this way, there is no need for ByteBuffer.flip() operations.
ByteBuf supports concurrent processes: while some data is written to the ByteBuf by one process, another one can read it. ByteBuf also has slice() operation and inner ref counts.
Allows to reuse ByteBufs, and as a result reduces Java Garbage Collector load. To make ByteBufPool usage more convenient, there are debugging and monitoring tools for allocated ByteBufs, including their stack traces.
To get a ByteBuf from the pool, use ByteBufPool.allocate(int size). A buffer of rounded up to the nearest power of 2 size will be allocated (for example, if size is 29, a ByteBuf of 32 bytes will be allocated).
To return ByteBuf to the ByteBufPool, use ByteBuf.recycle(). This recycle is recommended but not required - if you forget to do so, you will only give Garbage Collector a little more work to do.
You can explore an example of ByteBuf pool usage here
ByteBufQueue class provides effective management of multiple ByteBufs. It creates an optimized queue of several ByteBufs with FIFO rules. You can simply manage your queue with the following methods:
size. Otherwise creates a new ByteBuf of the
You can explore an example of ByteBuf queue usage here
This module also contains utility classes to manage resizing of underlying byte buffer,
String conversions, etc.
You can wrap your byte array into ByteBuf in the following ways:
ByteBuf can also be used to wrap other data types:
If you want to create a ByteBuf from scratch, you should use ByteBufPool.allocate(int size). This method either creates a new ByteBuf or returns one from the pool.
The core methods of ByteBuf are:
|head() / head(int pos)||gets/sets index of the ByteBuf from which bytes can be read|
|tail() / tail(int pos)||gets/sets index of the ByteBuf from which bytes can be written|
|limit()||returns length of the ByteBuf|
|drainTo(ByteBuf buf, int length)||drains ByteBuf to another ByteBuf, returns the number of elements to be drained|
|set(int index, byte b)||sets byte
|put(byte b)||puts given data in the
|getArray()||returns a byte array created from the ByteBuf from head to tail|
|asArray()||returns a byte array created from the ByteBuf from head to tail and recycles the ByteBuf|
|readByte() / readBoolean() / readChar() / readDouble() / readFloat() / readInt() / readLong() / readShort() / readString()||allows to read primitives and Strings from the
|writeByte(byte v) / writeBoolean(boolean v) / writeChar(char v) / writeDouble(double v) / writeFloat(float v) / writeInt(int v) / writeLong(long v) / writeShort(short v) / writeString(String s)||allows to write primitives and Strings to the
|slice() / slice (int length) / slice (int offset, int length)||returns a new SliceByteBuf which is a slice of your ByteBuf. By default, length is the number of bytes between head and tail, offset is head.|
|recycle()||recycles your ByteBuf by returning it to ByteBufPool.|