ByteBuffer之slice

405 阅读2分钟

以 HeapByteBuffer 为例分析。

/**
 * 创建一个新的ByteBuffer,但是与当前ByteBuffer共享子序列
 * Creates a new byte buffer whose content is a shared subsequence of
 * this buffer's content.
 * 
 * 
 * <p> The content of the new buffer will start at this buffer's current
 * position.  
 * 子序列范围内的数据是共享的。但是其position、limit、mark是相互独立  * 互不影响的
 * Changes to this buffer's content will be visible in the new
 * buffer, and vice versa; the two buffers' position, limit, and mark
 * values will be independent.
 *
 * <p> The new buffer's position will be zero, its capacity and its limit
 * will be the number of bytes remaining in this buffer, and its mark
 * will be undefined.  The new buffer will be direct if, and only if, this
 * buffer is direct, and it will be read-only if, and only if, this buffer
 * is read-only.  </p>
 *
 * @return  The new byte buffer
 */
public abstract ByteBuffer slice();

The content of the new buffer will start at this buffer's current position 新ByteBuffer内容的起始位置是当前ByteBuffer之position所指的字节数组下标处。这句注释对理解子序列异常重要。

首先需要明确一点,堆类型的缓冲池即HeapByteBuffer是指是在堆中分配空间的缓冲池,是JVM GC管理的空间。其实就是在HeapByteBuffer内部维护了一个byte类型的字节数组。

image.png

如图所示之着色数组

  1. 真正共享的子序列指的是着色数组
  2. 新ByteBuffer对应的byte数组。
  3. 新ByteBuffer其position值指向的位置并非是byte数组下标为0的位置,而是旧ByteBuffer其position值所指下标之处。
  4. 新ByteBuffer其get & put 操作空间即为着色部分。

综上所述,新旧ByteBuffer其真正共享是指着色数组对应的空间。

如何实现如图所示的功能呢?其实是ByteBuffer内部维护了一个offset属性值。该值的初始化值就是调用slice方法初始化新ByteBuffer时旧ByteBuffer其position的当前值。

后续操作新ByteBuffer也就是操作byte数组时,确认元素在数组中的下标时默认都会加减offset值来确定的。