Java NIO ByteBuffer 详解

什么是 ByteBuffer

ByteBuffer 是 Buffer 的一个具体实现,专门用于存储和操作字节数据。它提供了高效的、基于内存的 I/O 数据处理方式。

Buffer 类是构建 Java NIO 的基础,其中 ByteBuffer 类是 Buffer 子类中最受欢迎的。这是因为字节类型是最通用的类型。例如,我们可以在 JVM 中使用字节来组成其他非布尔基元类型。另外,我们可以使用字节在 JVM 和外部 I/O 设备之间传输数据。

类关系图

ByteBuffer 是 NIO 里用得最多的 Buffer,它包含两个实现方式:

  1. 堆缓冲区 HeapByteBuffer 是基于堆的实现,使用 JVM 的堆内存,读写操作效率低,会受到 GC 影响。
  2. 直接缓冲区 MappedByteBuffer(DirectByteBuffer)使用 OS 的内存,读写操作效率高,不会受到 GC 影响。但不主动析构,会造成内存的泄露。

这里扩展一下什么是内存泄露和内存溢出:

内存溢出:实际的数据量已经超过了当前机器的实际物理内存,比如数据量 2.5 GB,但实际物理内存只有 2 GB,将全部数据量全部读取到内存中去放不下那多出来的 0.5 GB,这就叫做溢出(OutOfMemoryException)。

内存泄露:实际的数据量虽然小于当前机器的实际物理内存,但还没读取完内存竟然不够用了,比如数据量 2 GB,实际物理内存也是 2 GB,但只读取了 1.8 GB 内存就不够了。造成内存泄露的原因大概两点:没有主动析构释放内存、内存碎片。

直接缓冲区与非直接缓冲区的区别?
区别维度 非直接缓冲区(Heap Buffer) 直接缓冲区(Direct Buffer)
创建方式 使用 ByteBuffer.allocate(size) 创建的缓冲区 使用 ByteBuffer.allocateDirect(size) 创建的缓冲区
内存分配 其数据存储在 Java 堆内存中。这意味着数据的存取需要经过 JVM 的内存管理,可能会涉及额外的内存复制(如从堆到内核空间) 其数据直接存储在操作系统的非易失性内存中,绕过了 Java 堆。这减少了 Java 堆与操作系统之间的数据拷贝,提高了效率,特别是在处理大块数据或进行系统调用时
性能角度 在小规模的数据操作中可能更快,因为它们避免了内存映射的开销,但对大块数据操作可能较慢 通常在处理大量数据或进行低级别 I/O(如文件读写或网络通信)时性能更好,因为减少了数据在用户空间和内核空间之间复制的开销
垃圾回收 遵循 Java 的垃圾收集机制,当不再引用时会被自动释放 不占用堆内存,因此不受 Java 堆大小的限制。但是,它们的生命周期管理更复杂,因为它们不会被垃圾收集器自动回收,除非没有其他强引用指向它们。

创建 ByteBuffer 的方法

包装现有数组

// 使用现有的 byte 数组创建缓冲区
byte[] byteArray = new byte[1024];
ByteBuffer wrappedBuffer = ByteBuffer.wrap(byteArray);

分配缓冲区

JDK 提供的 ByteBuffer 一旦分配空间,不可以动态调整大小,但是 Netty 对它进行了改进,支持了动态调整。

正是由于不能动态的扩充,如果添加的数据超过了容量,则会抛出 BufferOverflowException 异常。

// 分配一个容量为 1024 字节的缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);

分配直接缓冲区

// 分配一个直接缓冲区,性能较高
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);

通过字符串集和字符串创建

// 获取字符集,假设使用 UTF-8 编码
Charset charset = StandardCharsets.UTF_8;
ByteBuffer encode = charset.encode("Hello, World!");

核心结构

ByteBuffer 的核心结构围绕三个重要属性构建,这些属性决定了缓冲区的行为和状态:

Capacity(容量)

缓冲区的最大存储数据量,初始化时即固定,类似于数组的 Size。不可改变,决定了该缓冲区最多能容纳的字节数。

使用场景:确保缓冲区的容量足够大,以存储需要处理的数据。

ByteBuffer buffer = ByteBuffer.allocate(1024); // 容量为 1024 字节
System.out.println(buffer.capacity
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值