什么是ByteBuffer
Java 中的示例应用程序?请列出使用它的任何示例场景。
5 回答
这是对其用途和缺点的一个很好的描述。当您需要进行快速的低级 I/O 时,您基本上都会使用它。如果您要实现 TCP/IP 协议或者如果您正在编写数据库 (DBMS),那么这个类会派上用场。
ByteBuffer 类很重要,因为它构成了在 Java 中使用通道的基础。ByteBuffer类定义了对字节缓冲区的六类操作,如 Java 7 文档中所述:
Example code : Putting Bytes into a buffer.
// Create an empty ByteBuffer with a 10 byte capacity
ByteBuffer bbuf = ByteBuffer.allocate(10);
// Get the buffer's capacity
int capacity = bbuf.capacity(); // 10
// Use the absolute put(int, byte).
// This method does not affect the position.
bbuf.put(0, (byte)0xFF); // position=0
// Set the position
bbuf.position(5);
// Use the relative put(byte)
bbuf.put((byte)0xFF);
// Get the new position
int pos = bbuf.position(); // 6
// Get remaining byte count
int rem = bbuf.remaining(); // 4
// Set the limit
bbuf.limit(7); // remaining=1
// This convenience method sets the position to 0
bbuf.rewind(); // remaining=7
使用面向流的 API 的 Java IO 使用缓冲区作为用户空间中数据的临时存储来执行。DMA 从磁盘读取的数据首先被复制到内核空间的缓冲区,然后再传输到用户空间的缓冲区。因此有开销。避免它可以在性能上获得可观的收益。
如果有办法直接访问内核空间中的缓冲区,我们可以跳过用户空间中的这个临时缓冲区。Java NIO 提供了一种方法来做到这一点。
ByteBuffer
是 Java NIO 提供的几个缓冲区之一。它只是一个容器或储罐,用于读取数据或写入数据。上述行为是通过使用allocateDirect()
Buffer 上的 API 分配直接缓冲区来实现的。
这是一篇很棒的文章,解释了 ByteBuffer 的好处。以下是文章的重点:
- 无论是直接还是间接,ByteBuffer 的第一个优点是结构化二进制数据的有效随机访问(例如,答案之一中所述的低级 IO)。在 Java 1.4 之前,要读取此类数据,可以使用 DataInputStream,但不能进行随机访问。
以下是专门针对直接 ByteBuffer/MappedByteBuffer 的好处。请注意,直接缓冲区是在堆外创建的:
不受 gc 周期的影响:直接缓冲区在垃圾回收周期期间不会移动,因为它们位于堆外。TerraCota 的BigMemory缓存技术似乎在很大程度上依赖于这一优势。如果它们在堆上,它会减慢 gc 暂停时间。
性能提升:在流 IO 中,读取调用将需要系统调用,这需要在用户模式和内核模式之间进行上下文切换,反之亦然,这将是昂贵的,尤其是在文件被不断访问的情况下。但是,通过内存映射,这种上下文切换会减少,因为数据更有可能在内存中找到(MappedByteBuffer)。如果数据在内存中可用,则直接访问它而不调用操作系统,即没有上下文切换。
请注意,MappedByteBuffers 非常有用,尤其是在文件很大并且访问更频繁的几组块的情况下。
- 页面共享:内存映射文件可以在进程之间共享,因为它们分配在进程的虚拟内存空间中,并且可以跨进程共享。
在 Android 中,您可以在 C++ 和 Java 之间创建共享缓冲区(使用 directAlloc 方法)并在双方进行操作。