ByteBuffer核心在于状态机:创建分堆内、堆外、包装三种方式;四属性capacity/position/limit/mark协同满足0≤mark≤position≤limit≤capacity;读写必经写→flip→读三步;重用用clear/compact/rewind。

Java NIO 中的 ByteBuffer 是最常用、最核心的缓冲区类型,创建和操作它需理解其内存模型与状态机逻辑。关键不在“写多少行代码”,而在“什么时候调什么方法、为什么这么调”。
怎么创建 ByteBuffer
创建方式有三种,适用场景不同:
-
堆内缓冲区(推荐初学/中小数据):
ByteBuffer.allocate(1024)—— 在 JVM 堆中分配,GC 自动管理,创建快,适合短生命周期、小批量数据 -
堆外直接缓冲区(适合高性能 IO):
ByteBuffer.allocateDirect(1024)—— 分配在操作系统原生内存,绕过 JVM 堆拷贝,实现“零拷贝”,但创建慢、回收依赖 Cleaner 机制,适合长期持有、高频网络/文件读写 -
包装已有字节数组(复用内存):
ByteBuffer.wrap(byteArray)或ByteBuffer.wrap(byteArray, offset, length)—— 不分配新内存,直接将现有数组封装为 Buffer,常用于协议解析、内存复用场景
四个核心属性怎么协同工作
所有 Buffer 都靠这四个 int 值驱动:capacity、position、limit、mark。它们不是独立变量,而是构成一套状态指针系统:
-
capacity:固定值,创建时决定,不可变。比如
allocate(1024)→ capacity = 1024 -
position:当前读/写位置索引,从 0 开始。每次
put()或get()后自动递增 -
limit:读/写边界。写模式下通常等于 capacity;读模式下表示“最多能读到哪”,由
flip()设置 -
mark:可选标记位,通过
mark()记录 position,再用reset()回退 —— 类似书签,用于重复读或分段处理
关系恒成立:0 ≤ mark ≤ position ≤ limit ≤ capacity。违反即抛 BufferUnderflowException 或 BufferOverflowException。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
读写流程必须走对三步
ByteBuffer 不是普通容器,它有明确的“写→翻转→读”状态流转,跳过任意一步都会读不到数据或越界:
-
写入阶段:调用
put()(单字节)、put(byte[])(批量)、或channel.read(buffer)。此时 position 持续增长,limit 保持为 capacity -
翻转(flip):
buffer.flip()—— 这是关键转换:把 limit 设为当前 position(即写入了多少,就读多少),position 归零。从此 Buffer 进入“只读准备态” -
读取阶段:调用
get()、get(byte[])或channel.write(buffer)。position 随读取推进,直到等于 limit(hasRemaining()返回 false)
读完后如何重用缓冲区
不能直接再写——position 已走到末尾,limit 也卡在旧长度。需根据是否保留未读数据选择清理方式:
- clear():重置为初始写态 —— position = 0,limit = capacity。适合“全部数据已读完,准备全新写入”
- compact():仅压缩未读部分 —— 把 position 到 limit 之间的剩余数据移到开头,position 设为数据末尾,limit = capacity。适合“只读了一半,还要继续写新数据,但不想丢掉剩下那半”
- rewind():仅 position = 0,limit 不变。适合“想重头再读一遍已写入的内容”,不改变有效数据范围

















