java heapbytebuffer_java-nio之HeapByteBuffer与DirectByteBuffer详解

HeapByteBuffer与DirectByteBuffer二者的详细介绍与对比java

HeapByteBuffer

堆上的ByteBuffer对象,是调用ByteBuffer.allocate(n)所分配出来的,底层是经过new出来的新对象,因此必定在堆上分配的存储空间,属于jvm所可以控制的范围。c++

public static ByteBuffer allocate(int capacity) {

if (capacity < 0)

throw new IllegalArgumentException();

return new HeapByteBuffer(capacity, capacity);

}

DirectByteBuffer

对于这种Bytebuffer的建立,咱们能够看一下底层源码:web

public static ByteBuffer allocateDirect(int capacity) {

return new DirectByteBuffer(capacity);

}

一样是new出来的对象,咱们也认为是在jvm堆上分配的存储空间jvm

可是咱们能够查看到DirectByteBuffer底层的实现:svg

public native long allocateMemory(long var1);

...

long base = 0;

try {

base = unsafe.allocateMemory(size);

} catch (OutOfMemoryError x) {

Bits.unreserveMemory(size, cap);

throw x;

}

unsafe.setMemory(base, size, (byte) 0);

...

关键的是,allocateMemory是一个native方法,并非jvm可以控制的内存区域,一般称为堆外内存,通常是经过c/c++分配的内存(malloc)。spa

也就是说,对于DirectByteBuffer所生成的ByteBuffer对象,一部分是在jvm堆内存上,一部分是操做系统上的堆内存上,那么为了操做堆外内存,必定在jvm堆上的对象有一个堆外内存的引用:操作系统

public abstract class Buffer {

/**

* The characteristics of Spliterators that traverse and split elements

* maintained in Buffers.

*/

static final int SPLITERATOR_CHARACTERISTICS =

Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;

// Invariants: mark <= position <= limit <= capacity

private int mark = -1;

private int position = 0;

private int limit;

private int capacity;

// Used only by direct buffers

// NOTE: hoisted here for speed in JNI GetDirectBufferAddress

long address;

在DirectByteBuffer的父类中,能够看到address的一个变量,这个就是表示堆外内存所分配对象的地址,如此一来,jvm堆上的对象就会有一个堆外内存的一个引用,之因此须要这样作,是为了提高堆io的效率。code

对于HeapByteBuffer,数据的分配存储都在jvm堆上,当须要和io设备打交道的时候,会将jvm堆上所维护的byte[]拷贝至堆外内存,而后堆外内存直接和io设备交互。若是直接使用DirectByteBuffer,那么就不须要拷贝这一步,将大大提高io的效率,这种称之为零拷贝(zero-copy)。xml

并非说操做系统没法直接访问jvm中分配的内存区域,显然操做系统是能够访问全部的本机内存区域的,可是为何对io的操做都须要将jvm内存区的数据拷贝到堆外内存呢?是由于jvm须要进行GC,若是io设备直接和jvm堆上的数据进行交互,这个时候jvm进行了GC,那么有可能会致使没有被回收的数据进行了压缩,位置被移动到了连续的存储区域,这样会致使正在进行的io操做相关的数据所有乱套,显然是不合理的,因此对io的操做会将jvm的数据拷贝至堆外内存,而后再进行处理,将不会被jvm上GC的操做影响。对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值