以 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类型的字节数组。
如图所示之着色数组。
- 真正共享的子序列指的是
着色数组。 - 新ByteBuffer对应的byte数组。
- 新ByteBuffer其position值指向的位置并非是byte数组下标为0的位置,而是旧ByteBuffer其position值所指下标之处。
- 新ByteBuffer其get & put 操作空间即为着色部分。
综上所述,新旧ByteBuffer其真正共享是指着色数组对应的空间。
如何实现如图所示的功能呢?其实是ByteBuffer内部维护了一个offset属性值。该值的初始化值就是调用slice方法初始化新ByteBuffer时旧ByteBuffer其position的当前值。
后续操作新ByteBuffer也就是操作byte数组时,确认元素在数组中的下标时默认都会加减offset值来确定的。