Buffer
的种类
就类型而言,Buffer
总共有七种基本的对象,但是从底层来看,最大的区别只在于Heap
和Direct
的区别。
Heap
:JVM
堆内存
Direct
:OS
直接内存
I/O
的关系
和硬件设备打交道,必定是操作系统
os
的工作。而
JVM
只是OS
之上的再组织,根源操作仍然是OS
进行的操作。
两种Buffer
的对比
那么,
Heap
和Direct
在哪呢。根据前文所述,
Heap
就在JVM
内部,Direct
应该在OS
。不过我们先申明几点
- 对象:不论内存空间在哪,
JVM
中总有对象- 内存:不论内存在哪,
OS
总能管理- 数据交换:
I/O
要交换的数据,一定都在OS
管理下
为什么要拷贝
HeapMemory
到OS
?
OS
命名能够管理任意的内存,虽然heap
在JVM
内部,但是仍然能够拿到,为甚么需要拷贝出来呢?由于
GC
垃圾回收的缘故,导致内存数据可能被挪动,但是OS
自有管理,不会去迁就JVM
。导致操作数据时会发生数据改变或丢失。
但是,
OS
直接和device
进行交互,交换数据一定要让OS
进行管理。
OS
对HeapMemory
直接进行管理,数据不安全,需要先拷贝出来。
Direct
如何引用OS
内存?
Buffer
中存在一个address
属性,这里就是堆外内存
地址,直接在OS中JVM外
进行数据操作。因此不涉及交换数据拷贝操作,效率更高。
两种方式何时释放?
heap
heapObject
销毁时释放heapMemory
OS
完成I/O
操作后自动释放
direct
directObject
销毁时自动释放address
的内存,也就是directMemory
内存映射文件对象
direct
的办法,就是在JVM
内存中的变化,直接改变到OS
上。不是调用什么去完成操作,而是
直接操作
的效果。
direct
继承的Mapped
就是干这个的。
public class MappedMain {
public static void main(String[] args) throws Exception{
RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
MappedByteBuffer mappedByteBuffer = file.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 26);
char ch = 'a';
while(mappedByteBuffer.hasRemaining()){
mappedByteBuffer.putChar(ch);
ch += 1;
}
file.close();
}
}
我们做了什么,我们只是操作了内存中的MappedByteBuffer
,不过,你文件浏览器打开文件看看。
文件直接就已经被修改了。
也就是说,我们内存中的直接操作,直接影响了OS
的文件内容。
小结
所以说Direct
为什么快呢。