Java中ByteBuffer有什么用?

发布于 2024-10-14 16:36:02 字数 1436 浏览 10 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

三五鸿雁 2024-10-21 16:36:02

很好地描述了它的用途和缺点。每当您需要执行快速低级 I/O 时,您基本上都会使用它。如果您要实现 TCP/IP 协议或者要编写数据库 (DBMS),那么此类将会派上用场。

This is a good description of its uses and shortcomings. You essentially use it whenever you need to do fast low-level I/O. If you were going to implement a TCP/IP protocol or if you were writing a database (DBMS) this class would come in handy.

分分钟 2024-10-21 16:36:02

ByteBuffer 类很重要,因为它构成了在 Java 中使用通道的基础。 ByteBuffer 类定义了对字节缓冲区的六类操作,如 Java 7 文档中所述

  • 绝对和相对获取put< /a> 读取和写入单个字节的方法;


  • 相对 bulk get 方法,将连续的字节序列从此缓冲区传输到数组中;

  • 相对 bulk put 方法,将连续的字节序列从字节数组或其他字节缓冲区传输到此缓冲区;

  • 绝对和相对的 get 和 put 方法,用于读取和写入其他基本类型的值,并将它们转换为序列
    特定字节顺序的字节;

  • 创建视图缓冲区的方法,允许将字节缓冲区视为包含某些其他基本类型的值的缓冲区;和

  • 压缩方法压缩复制切片字节缓冲区。

示例代码:将字节放入缓冲区。

    // 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

The ByteBuffer class is important because it forms a basis for the use of channels in Java. ByteBuffer class defines six categories of operations upon byte buffers, as stated in the Java 7 documentation:

  • 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.

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
︶ ̄淡然 2024-10-21 16:36:02

使用面向流的 API 的 Java IO 是使用缓冲区作为用户空间内数据的临时存储来执行的。通过 DMA 从磁盘读取的数据首先复制到内核空间的缓冲区,然后传输到用户空间的缓冲区。因此存在开销。避免它可以显着提高性能。

如果有一种方法可以直接访问内核空间中的缓冲区,我们可以跳过用户空间中的这个临时缓冲区。 Java NIO 提供了一种方法来做到这一点。

ByteBuffer 是 Java NIO 提供的几个缓冲区之一。它只是一个用于读取数据或写入数据的容器或存储罐。上述行为是通过使用 Buffer 上的 allocateDirect() API 分配直接缓冲区来实现的。

字节缓冲区的 Java 文档包含有用的信息。

Java IO using stream oriented APIs is performed using a buffer as temporary storage of data within user space. Data read from disk by DMA is first copied to buffers in kernel space, which is then transfer to buffer in user space. Hence there is overhead. Avoiding it can achieve considerable gain in performance.

We could skip this temporary buffer in user space, if there was a way directly to access the buffer in kernel space. Java NIO provides a way to do so.

ByteBuffer is among several buffers provided by Java NIO. Its just a container or holding tank to read data from or write data to. Above behavior is achieved by allocating a direct buffer using allocateDirect() API on Buffer.

Java Documentation of Byte Buffer has useful information.

没企图 2024-10-21 16:36:02

这里是一篇很好的文章,解释了 ByteBuffer 的优点。以下是本文的要点:

  • 无论是直接还是间接,ByteBuffer 的第一个优点是结构化二进制数据的高效随机访问(例如,低级 IO,如其中之一所述)答案)。在 Java 1.4 之前,要读取此类数据,可以使用 DataInputStream,但不能随机访问。

以下是直接 ByteBuffer/MappedByteBuffer 的具体优点。请注意,直接缓冲区是在堆外部创建的:

  1. 不受 gc 周期影响:直接缓冲区在垃圾收集周期期间不会移动,因为它们驻留在堆外部。 TerraCota 的 BigMemory 缓存技术似乎很大程度上依赖于这一优势。如果它们位于堆上,则会减慢 gc 暂停时间。

  2. 性能提升:在流 IO 中,读取调用需要系统调用,这需要在用户模式和内核模式之间进行上下文切换,反之亦然,这将是昂贵的,尤其是在不断访问文件的情况下。然而,通过内存映射,这种上下文切换会减少,因为数据更有可能在内存(MappedByteBuffer)中找到。如果数据在内存中可用,则直接访问它而无需调用操作系统,即无需上下文切换。

请注意,MappedByteBuffers 非常有用,尤其是在文件很大并且访问频率较高的几组块的情况下。

  1. 页面共享:内存映射文件可以在进程之间共享,因为它们分配在进程的虚拟内存空间中,并且可以跨进程共享。

Here is a great article explaining ByteBuffer benefits. Following are the key points in the article:

  • First advantage of a ByteBuffer irrespective of whether it is direct or indirect is efficient random access of structured binary data (e.g., low-level IO as stated in one of the answers). Prior to Java 1.4, to read such data one could use a DataInputStream, but without random access.

Following are benefits specifically for direct ByteBuffer/MappedByteBuffer. Note that direct buffers are created outside of heap:

  1. 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.

  2. 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.

Note that MappedByteBuffers are very useful especially if the files are big and few groups of blocks are accessed more frequently.

  1. Page sharing: Memory mapped files can be shared between processes as they are allocated in process's virtual memory space and can be shared across processes.
陈独秀 2024-10-21 16:36:02

在 Android 中,您可以在 C++ 和 Java 之间创建共享缓冲区(使用 directAlloc 方法)并在双方操作它。

In Android you can create shared buffer between C++ and Java (with directAlloc method) and manipulate it in both sides.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文