Java中ByteBuffer的示例应用程序是什么?请列出任何使用这种方法的示例场景。
ByteBuffer类很重要,因为它构成了在Java中使用通道的基础。ByteBuffer类定义了六类对字节缓冲区的操作,如Java 7文档中所述:
Absolute and relative get and put methods that read and write single bytes; Relative bulk get methods that transfer contiguous sequences of bytes from this buffer into an array; Relative bulk put methods that transfer contiguous sequences of bytes from a byte array or some other byte buffer into this buffer; Absolute and relative get and put methods that read and write values of other primitive types, translating them to and from sequences of bytes in a particular byte order; Methods for creating view buffers, which allow a byte buffer to be viewed as a buffer containing values of some other primitive type; and Methods for compacting, duplicating, and slicing a byte 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提供的几个缓冲区之一。它只是一个用于读取数据或写入数据的容器或容器。上述行为是通过在buffer上使用allocateDirect() API分配一个直接缓冲区来实现的。
Java文档中的字节缓冲区有有用的信息。
这里有一篇很好的文章解释了ByteBuffer的好处。本文的重点如下:
ByteBuffer的第一个优点,不管它是直接的还是间接的,都是对结构化二进制数据的高效随机访问(例如,在一个答案中所述的低级IO)。在Java 1.4之前,要读取这样的数据,可以使用DataInputStream,但没有随机访问。
以下是直接ByteBuffer/MappedByteBuffer的好处。注意,直接缓冲区是在堆之外创建的:
Unaffected by gc cycles: Direct buffers won't be moved during garbage collection cycles as they reside outside of heap. TerraCota's BigMemory caching technology seems to rely heavily on this advantage. If they were on heap, it would slow down gc pause times. Performance boost: In stream IO, read calls would entail system calls, which require a context-switch between user to kernel mode and vice versa, which would be costly especially if file is being accessed constantly. However, with memory-mapping this context-switching is reduced as data is more likely to be found in memory (MappedByteBuffer). If data is available in memory, it is accessed directly without invoking OS, i.e., no context-switching.
请注意,mappedbytebuffer非常有用,特别是当文件很大并且频繁访问少数组块时。
页面共享:内存映射文件可以在进程之间共享,因为它们分配在进程的虚拟内存空间中,并且可以跨进程共享。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap