本文章来自于本人个人博客:java nio 缓冲区(二)
一,创建缓冲区
1.缓冲区的创建有两种方式,分别是ByteBuffer.allocate([int])或者ByteBuffer.wrap(byte[]),第一种方式是创建一个分配了int个字节的缓冲区,而第二种方式是在现有字节数组之上创建一个缓冲区,这个缓冲区的capacity就是数组的长度。
2.Buffer类的其它子类创建缓冲区也是一样的:CharBuffer.allocate(int)或者CharBuffer.wrap(byte[])
二,缓冲区复制
缓冲区的复制有两个方法:duplicate()和slice(),duplicate方法会创建一个新的buffer,并且与原始buffer共同指向同一个内存区域;slice()方法是在调用buffer.position(4).limit(21)后调用buffer.slice()将截取缓冲区4-21之间的字节数组。
三,字节缓冲区
1.字节顺序
在缓冲区中,字节顺序被称为大端字节和小端字节。大端字节的意思是将一个数值的字节按照正常的顺序读取方式读入缓冲区,小端字节是讲一个数值的字节按照高位在前地位在后的顺序读进内存,例如:5870099的十进制值为:0x037fb4c7,这是正常顺序,跟我们平常使用的一样,此为大端字节,而如果使用小端字节,则输出将是0xc7b47f03。
四,直接缓冲区
在java中,数组是对象,而数据存储在对象中的方式在不同JVM实现中都各有不同。处于这一原因,引入了直接缓冲区概念。直接缓冲区被用于与佟冬和固有I/O进程交互,他们通过使用固有代码来告知操作系统直接释放或填充内存区域,对用于佟冬直接或原始存取的内存区域中的字节元素的存储尽了最大的努力。
直接字节缓冲区通常是I/O操作最好的选择,在设计方面,它们支持JVM可用的最高效I/O机制,非直接字节缓冲区可以被传递给通道,但是这样可能导致性能损耗。通常非直接缓冲不可能成为一个本地I/O操作目标。如果向一个非直接缓冲中写入数据,则调用方式如下步骤:
1.创建一个临时的直接ByteBuffer对象
2.将非直接缓冲区的内容复制到临时缓冲中
3.使用临时缓冲区执行低层次I/O操作
4.临时缓冲区对象离开作用域,并最终成为被回收的无用数据
从上面的步骤可以知道,非直接缓冲区在读写内存时,是通过一个临时的直接缓冲区的桥接来进行的,但是对于直接缓冲区,每一次的创建都会消耗很大的资源,这无疑加重了程序的负担。
直接缓冲区使用的内存是通过调用本地操作系统方面的代码分配的,绕过了标准JVM堆栈。建立和销毁直接缓冲区会明显比具有堆栈的缓冲区更加破费,这取决于主操作系统以及JVM实现。
直接缓冲区是通过调用ByteBuffer.allocateDirect()方法创建的,注意,用wrap()方法创建的缓冲区总是非直接的。
java nio 缓冲区(二)