bytebuffer分堆内(allocate)和堆外(allocatedirect)两种;写数据可通过channel.read或buffer.put,写完需flip才能读;读数据用get或channel.write,读完可用clear或compact复用;关键状态位为capacity、position、limit。

怎么分配 ByteBuffer
Java NIO 中,ByteBuffer 提供两种内存分配方式:
-
堆内缓冲区:用
ByteBuffer.allocate(size),数据存在 JVM 堆里,创建快、回收由 GC 管理,适合普通场景、小数据量操作; -
堆外直接缓冲区:用
ByteBuffer.allocateDirect(size),数据存在操作系统内存(native memory),不走堆,I/O 时可实现零拷贝,适合高频读写或大文件传输,但分配/释放慢,需注意内存泄漏风险。
怎么往 ByteBuffer 写数据
写入数据主要有两种途径:
- 从 Channel 读取:调用
channel.read(buffer),自动把通道数据写入 buffer 的当前 position 位置,返回实际读取字节数; - 手动 put 数据:调用
buffer.put(byte)、buffer.putChar('a')或buffer.put(byte[])等方法,逐个或批量写入,position 随之递进;
写完后,buffer 的 position 指向下一个可写位置,limit 仍等于容量,此时不能直接读——需要先翻转。
怎么从 ByteBuffer 读数据
读取前必须调用 flip(),它会把 limit 设为当前 position,再把 position 归零,让 buffer 进入“只读就绪”状态。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 用
buffer.get()逐字节读,每次读完 position 自动加 1; - 用
buffer.get(i)读指定索引,不改变 position,适合重复访问; - 用
channel.write(buffer)把 buffer 内容写到通道,同样依赖当前 position 和 limit;
读完若要复用 buffer,可调用 clear()(重置 position=0、limit=capacity)或 compact()(把未读数据移到开头,position 设为未读数据长度)。
几个关键状态位要盯住
ByteBuffer 内部靠三个整数控制读写边界:
- capacity:缓冲区总容量,创建后不可变;
- position:当前读/写位置,写时递增、读时也递增;
-
limit:读/写操作的上界,
flip()后 limit = 原 position,clear()后 limit = capacity;
任何时候 position 都不能超过 limit,否则抛 BufferOverflowException 或 BufferUnderflowException。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










