clear()并非清空数据,而是重置指针:position=0、limit=capacity、mark=-1,仅修改元数据不操作底层数组,实现高效复用。

clear() 不是清空数据,而是重置读写指针——这是理解 Java NIO Buffer 行为的关键前提。它不碰底层数组一个字节,只改三个字段:position 归 0、limit 设为 capacity、mark 置 -1。
clear() 的真实执行动作
调用 clear() 时,JVM 实际执行的是三条字段赋值指令(字节码层面无内存操作):
- position = 0:下一次 put() 从索引 0 开始写
- limit = capacity:整个缓冲区再次对写入开放
- mark = -1:清除标记位,使 reset() 失效
为什么不清除底层数组?
这是性能与复用设计的取舍:
- 堆内 ByteBuffer 的 backing array 是普通 byte[],GC 不保证立即回收或覆写;堆外内存更不会被 JVM 自动清零
- 反复 new buffer 开销大,NIO 鼓励复用;clear() 让同一块内存快速进入“可覆盖”状态,而非等待 GC 或手动 new
- 真正需要擦除敏感信息(如密码、密钥)时,必须手动填充零:
Arrays.fill(buffer.array(), (byte)0)(仅限堆内)或使用MemoryUtil.memSet()(堆外)
clear() 后还能读到旧数据吗?
不能直接读,但数据仍在内存里:
立即学习“Java免费学习笔记(深入)”;
- clear() 后 position=0、limit=capacity,此时若调用 get(),会因 position
- 常见误操作:
clear(); get()→ 表面能读,实则读的是历史脏数据,逻辑上已不可信 - 安全做法:明确区分用途——非敏感场景靠覆盖保障;敏感场景必须主动擦除,不能依赖 clear()
clear() 和 compact() 的本质区别
二者都为重入写模式服务,但对待未读数据的态度截然不同:
- clear():彻底放弃未读部分,指针回归全容量可写态。适用于“整包处理完毕,准备收下一条完整消息”
- compact():把 position 到 limit 之间的未读字节移到开头,position 移到已复制长度之后,limit 设为 capacity。适用于“只读了半包,还要继续接收后续数据拼成完整包”


















