ReadOnlyBufferException 是 JVM 在检测到对只读缓冲区(如调用 asReadOnlyBuffer() 创建的 ByteBuffer)执行 put、compact 等写操作时自动抛出的运行时异常,用于强制阻止非法写入,而非供捕获使用的控制手段。

ReadOnlyBufferException 是 Java NIO 中用于在运行时阻止对只读缓冲区(ByteBuffer、CharBuffer 等)执行写操作的异常。它不是你主动“通过”它来阻止写入的工具,而是 JVM 在检测到非法写操作时自动抛出的保护机制——它的存在本身,就是阻止非法写入的方式。
只读缓冲区的创建方式决定其不可变性
只读缓冲区必须显式创建,常见方式包括:
- 调用 asReadOnlyBuffer():基于已有缓冲区生成一个逻辑上只读的新视图(底层数据仍可被原缓冲区修改)
- 使用 ByteBuffer.wrap(byte[]) 后再调用 asReadOnlyBuffer():确保该视图不能修改原始数组内容
- 从 MappedByteBuffer 映射为只读模式(如 FileChannel.map(..., MapMode.READ_ONLY))
哪些操作会触发 ReadOnlyBufferException
一旦缓冲区被标记为只读,以下任何写操作都会立即抛出该异常:
- put(byte)、put(int, byte)、put(byte[])
- compact()(因需重排并写入数据)
- flip() 和 rewind() 不会触发,它们只改变位置/限制,不写数据
- duplicate() 或 slice() 返回的副本默认继承只读属性,后续写入同样失败
正确使用只读缓冲区的实践建议
避免意外写入的关键是明确区分读写意图:
- 对外提供数据时,优先返回 asReadOnlyBuffer() 视图,防止调用方误改内部状态
- 不要依赖 try-catch ReadOnlyBufferException 来“控制流程”,它属于编程错误,应在开发/测试阶段暴露并修复
- 若需同时支持读写与只读访问,应维护两套缓冲区引用,或用包装类封装访问逻辑
- 注意:只读性是缓冲区对象级别的属性,不影响底层 byte[] 是否可变;若原始数组仍被其他可写缓冲区持有,数据仍可能被修改
ReadOnlyBufferException 的作用不是让你去捕获它,而是提醒你——代码中出现了违背缓冲区语义的写操作。修复方式是检查缓冲区来源、确认是否误用了只读视图,或改用可写副本处理数据。

















