NIO之缓冲区【直接和非直接缓冲区】
直接与非直接缓冲区
字节缓冲区跟其他缓冲区类型最明显的不同在于,它们可以成为通道所执行的 I/O 的源头和/或目标。其实发现通道只接收ByteBuffer作为参数这个将Channel的时候会发现。
类型 | 优点 | 缺点 |
---|---|---|
直接缓冲区 | 在虚拟机内存外,开辟的内存, IO操作直接进行,没有再次复制 |
创建和销毁开销大 |
非直接缓冲区 | 在虚拟机内存中创建,易回收 | 但占用虚拟机内存开销, 处理中有复制过程。 |
直接缓冲区
直接缓存区是在虚拟机内存外,开辟的内存,IO操作直接进行,不再对其进行复制,但创建和销毁开销大。
非直接缓冲区
非直接缓存区在虚拟机内存中创建,易回收,但占用虚拟机内存开销,处理中有复制过程。
直接和非直接缓冲区解释
操作系统在内存区域中进行I/O操作,这些内存区域,就操作系统方面而言,是相连的字节序列。所以,只有字节缓冲区有资格参与I/O操作。操作系统会直接存取进程——在本例中是JVM进程的内存空间,以传输数据。这也意味着I/O操作的目标内存区域必须是连续的字节序列。在JVM中,字节数组可能不会在内存中连续存储,或者无用存储单元收集可能随时对其进行移动。在Java中,数组是对象,而数据存储在对象中的方式在不同的JVM实现中都各有不同。出于这一原因,引入了直接缓冲区的概念。
直接字节缓冲区通常是I/O操作最好的选择。在设计方面,它们支持JVM可用的最高效I/O机制。非直接字节缓冲区可以被传递给通道,但是这样可能导致性能损耗。通常非直接缓冲不可能成为一个本地I/O操作的目标。如果向一个通道中传递一个非直接ByteBuffer对象用于写入,通道可能会在每次调用中隐含地进行下面的操作:
- 创建一个临时的直接ByteBuffer对象。
- 将非直接缓冲区的内容复制到临时缓冲中。
- 使用临时缓冲区执行低层次I/O操作。
- 临时缓冲区对象离开作用域,并最终成为被回收的无用数据。
直接缓冲区是I/O的最佳选择,但可能比创建非直接缓冲区要花费更高的成本。直接缓冲区使用的内存是通过调用本地操作系统方面的代码分配的,绕过了标准JVM堆栈。建立和销毁直接缓冲区会明显比具有堆栈的缓冲区更加破费,这取决于主操作系统以及JVM实现。直接缓冲区的内存区域不受无用存储单元收集支配,因为它们位于标准JVM堆栈之外。
直接ByteBuffer是通过调用ByteBuffer.allocateDirect()函数产生的,注意用一个wrap()函数所创建的被包装的缓冲区总是非直接的。
public abstract class ByteBuffer extends Buffer implements Comparable {
// This is a partial API listing
public static ByteBuffer allocate(int capacity)
public static ByteBuffer allocateDirect(int capacity)
public abstract boolean isDirect();
}
- 1
- 2
- 3
- 4
- 5
- 6
使用直接缓冲区有两种方式:
- 缓冲区创建的时候分配的是直接缓冲区
- 在FileChannel上调用map()方法,将文件直接映射到内存中创建
文章来源: dpb-bobokaoya-sm.blog.csdn.net,作者:波波烤鸭,版权归原作者所有,如需转载,请联系作者。
原文链接:dpb-bobokaoya-sm.blog.csdn.net/article/details/89198608
- 点赞
- 收藏
- 关注作者
评论(0)