bytebuffer 的 mark() 和 reset() 用于标记并回退 position,mark 初始为 -1,reset 前需先 mark,否则抛 invalidmarkexception;get/put/flip/rewind/clear 会丢弃 mark,compact 不会;reset 不改变 mark 值,可重复使用;非线程安全,复杂场景建议用 duplicate、slice 或手动保存 position。

Java NIO 中 ByteBuffer 的 mark() 和 reset() 方法用于临时“标记”当前读取位置(position),之后可通过 reset() 快速回退到该位置,避免重复解析或手动保存/恢复 position。它不是“撤销操作”,也不影响 limit 或 capacity,只作用于 position 与 mark 之间的关系。
mark() 和 reset() 的基本行为
mark() 将当前 position 值保存到内部的 mark 字段;reset() 则把 position 设为之前标记的值。注意:
- mark 初始为 -1(未标记);
- 只有调用过 mark() 后,reset() 才有效,否则抛 InvalidMarkException;
- 多数修改 position 的操作(如 get()、put()、flip()、rewind()、clear())会**丢弃 mark**(设为 -1),但 compact() 不会丢弃 mark(JDK 8+ 行为)。
典型使用场景:预读 + 回退
常见于协议解析中需要“试探性读取”——比如判断接下来是 header 还是 payload,或识别消息类型前先 peek 几个字节:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 调用
buffer.mark()记录起始读位置; - 用
get()或getShort()等读取若干字节做判断; - 若需按原格式继续处理,就调用
buffer.reset()回退 position; - 若确认无需回退,可忽略 mark(后续操作会自动清除它)。
示例:
ByteBuffer buf = ByteBuffer.wrap(new byte[]{0x01, 0x02, 0x03, 0x04});
buf.mark(); // mark = 0
byte b1 = buf.get(); // position=1, b1=0x01
byte b2 = buf.get(); // position=2, b2=0x02
if (b1 == 0x01 && b2 == 0x02) {
buf.reset(); // position 回到 0
System.out.println(buf.getShort()); // 读出 0x0102 = 258
}
注意事项与常见陷阱
mark 不是事务边界:它不保存数据状态,也不阻止写入或其它字段变更;
clear() / flip() 会清除 mark:这两个方法常用于切换读/写模式,调用后 mark 变为 -1,不能再 reset;
reset 后 mark 保持不变:reset 只改 position,mark 值仍为原标记值,可再次 reset(除非中间调用了丢弃 mark 的操作);
多线程不安全:mark/position 是实例状态,ByteBuffer 非线程安全,共享 buffer 时需同步。
替代方案对比
若逻辑复杂或需多次回退,mark/reset 可能不够用:
- 用 buffer.duplicate() 创建轻量副本,各自独立 position/mark;
- 用 buffer.slice() 截取子视图,适合固定段落解析;
- 手动保存 int savedPos = buffer.position(),再 buffer.position(savedPos),更直观可控,且不受 mark 生命周期限制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










