MINA应用程序使用的字节缓冲区。
这是ByteBuffer的替代品。 MINA不直接使用NIO ByteBuffer有两个原因:
- 它不提供有用的getter和putter,如fill,get / putString和get / putAsciiInt()。
- 由于其固定容量,很难编写可变长度数据
注意:
这将在MINA 3中发生变化.MINA在nio ByteBuffer之上拥有自己的包装器的主要原因是具有可扩展的缓冲区。这是一个非常糟糕的决定。缓冲区只是缓冲区:在使用之前临时存储临时数据的地方。存在许多其他解决方案,例如定义依赖于NIO ByteBuffers列表的包装器,而不是仅仅因为我们想要扩展缓冲区容量而将现有缓冲区复制到更大的缓冲区。
在过滤器中使用InputStream而不是字节缓冲区也可能更为舒适,因为它并不意味着存储数据的性质:它可以是字节数组,字符串,消息......
最后,并非最不重要的是,当前的实现击败了一个目标:零拷贝策略(即,一旦我们从套接字读取数据,我们希望避免稍后复制)。当我们使用可扩展字节缓冲区时,如果我们必须管理大消息,我们肯定会复制这些数据。假设MINA ByteBuffer只是NIO ByteBuffer之上的包装器,使用直接缓冲区时这可能是一个真正的问题。
IoBuffer操作
分配新的缓冲区
IoBuffer是一个抽象类,因此无法直接实例化。要分配IoBuffer,我们需要使用两个allocate()方法之一。
// Allocates a new buffer with a specific size, defining its type (direct or heap)
public static IoBuffer allocate(int capacity, boolean direct)
// Allocates a new buffer with a specific size
public static IoBuffer allocate(int capacity)
allocate()方法接受一个或两个参数。第一种形式有两个参数:
- capacity - 缓冲区的容量
- 直接型缓冲区。如果获取直接缓冲区为true,则为false以获取堆缓冲区
默认缓冲区分配由SimpleBufferAllocator处理
或者,也可以使用以下形式
// Allocates heap buffer by default.
IoBuffer.setUseDirectBuffer(false);
// A new heap buffer is returned.
IoBuffer buf = IoBuffer.allocate(1024);
使用第二种形式时,不要忘记先设置默认缓冲区类型,否则默认情况下会获得堆缓冲区。
创建自动扩展缓冲区
使用java NIO API创建自动扩展缓冲区并不是很容易,因为缓冲区的大小是固定的。拥有可以自动扩展需求的缓冲区对于网络应用程序来说是一个很大的优势。为了解决这个问题,IoBuffer引入了autoExpand属性。它会自动扩展其容量并限制值。
让我们看看如何创建自动扩展缓冲区:
IoBuffer buffer = IoBuffer.allocate(8);
buffer.setAutoExpand(true);
buffer.putString("12345678", encoder);
// Add more to this buffer
buffer.put((byte)10);
如果在上面的示例中编码数据大于8个字节,则底层ByteBuffer由场景后面的IoBuffer重新分配。它的容量将加倍,其限制将增加到字符串写入的最后位置。此行为与StringBuffer类的工作方式非常相似。
注意:
这种机制很可能会从MINA 3.0中删除,因为它并不是处理增加的缓冲区大小的最佳方法。它应该被隐藏列表的InputStream或固定大小的ByteBuffers数组所取代。
创建自动缩小缓冲区
有些情况需要从缓冲区释放额外分配的字节,以保留内存。 IoBuffer提供autoShrink属性来满足需要。如果启用了autoShrink,则在调用compact()时,IoBuffer会将缓冲区的容量减半,并且仅使用当前容量的1/4或更少。要手动收缩缓冲区,请使用shrink()方法。
让我们看看这个:
IoBuffer buffer = IoBuffer.allocate(16);
buffer.setAutoShrink(true);
buffer.put((byte)1);
System.out.println("Initial Buffer capacity = "+buffer.capacity());
buffer.shrink();
System.out.println("Initial Buffer capacity after shrink = "+buffer.capacity());
buffer.capacity(32);
System.out.println("Buffer capacity after incrementing capacity to 32 = "+buffer.capacity());
buffer.shrink();
System.out.println("Buffer capacity after shrink= "+buffer.capacity());
我们最初将容量分配为16,并将autoShrink属性设置为true。
让我们看看这个的输出:
Initial Buffer capacity = 16
Initial Buffer capacity after shrink = 16
Buffer capacity after incrementing capacity to 32 = 32
Buffer capacity after shrink= 16
让我们休息一下并分析输出:
1.初始缓冲区容量为16,因为我们创建了具有此容量的缓冲区。在内部,这成为缓冲区的最小容量
2.在调用shrink()之后,容量保持为16,因为容量永远不会小于最小容量
3.将容量增加到32后,容量变为32
4.调用shrink(),将容量减少到16,从而消除额外的存储空间
同样,这个机制应该是默认机制,而不需要明确地告诉缓冲区它可以缩小。
缓冲区分配
IoBufferAllocater负责分配和管理缓冲区。要精确控制缓冲区分配策略,请实现IoBufferAllocater接口。
MINA附带以下IoBufferAllocater实现:
1.SimpleBufferAllocator(默认) - 每次创建一个新缓冲区 2.CachedBufferAllocator - 缓存可能在扩展期间重用的缓冲区
使用新的可用JVM,使用缓存的IoBuffer不太可能提高性能。
您可以实现自己的IoBufferAllocator实现,并在IoBuffer上调用setAllocator()来使用它。