compact()方法将ByteBuffer中position到limit间的未读数据移至缓冲区起始,重设position为移动后长度、limit为capacity,保留未读数据以便继续写入。

compact() 方法的作用是把 ByteBuffer 中尚未读取完的数据(即从 position 到 limit 之间的字节)移动到缓冲区起始位置,并将 position 设置为已复制数据的末尾,limit 设置为容量上限,从而腾出后面的空间继续写入。它适用于“读多写少”或“边读边写”的场景,比如网络通信中处理半包、粘包时清理已处理数据、保留未读完的部分。
compact() 的核心行为
调用前需确保已完成对当前有效数据的读取处理(如解析、解码),否则未读数据会被覆盖或丢弃。它的实际效果等价于:
- 把
[position, limit)区间的字节,逐个复制到[0, limit - position)位置; - 设置
position = limit - position(即新数据将追加在已保留数据之后); - 设置
limit = capacity(整个缓冲区再次可用于写入); - 不改变
capacity和mark(如有 mark,通常会失效,建议 compact 前清除)。
典型使用流程(以 SocketChannel 读写为例)
假设一个 ByteBuffer 用于接收网络数据,已读入部分数据但未全部处理完:
- 调用
channel.read(buffer)后,buffer 的position指向新数据末尾; - 用
flip()切换为读模式,处理已读数据(如解析协议头); - 若发现还有未读完的完整包(例如只读了包头,或包体不全),就调用
compact(); - 再调用
channel.read(buffer)继续追加后续数据到 buffer 尾部。
注意事项和常见误区
compact() 不等于 clear():clear 会丢弃所有已有数据,而 compact 会保留未读部分;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
不能在读模式下直接 compact:必须先完成读操作(如已调用 get() 或 arrayOffset + remaining 处理完毕),否则 position 未推进,compact 会把“未读”区域错误地移走;
写入前无需 flip:compact 后 buffer 自动处于可写状态(position 在有效数据尾,limit = capacity),直接 write 即可;
如果 buffer 中剩余未读数据量较大,频繁 compact 可能引发数组复制开销,此时可考虑扩容或换用 CompositeByteBuf(Netty)等更高效结构。

















