NIO ByteBuffer的allocate与allocateDirect区别(HeapByteBuffer与DirectByteBuffer的区别)

本文深入探讨了Java中HeapByteBuffer与DirectByteBuffer的区别,包括它们的内存分配方式、创建与读写性能,以及适用场景。HeapByteBuffer创建速度快但读写效率低,适用于一次性使用的场景;而DirectByteBuffer创建速度慢但读写效率高,尤其适合频繁的本地IO操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

其中allocateDirect分配的字节缓冲区用中文叫做直接缓冲区(DirectByteBuffer),用allocate分配的ByteBuffer叫做堆字节缓冲区(HeapByteBuffer)..

其实根据类名就可以看出,HeapByteBuffer所创建的字节缓冲区就是在jvm堆中的,即内部所维护的java字节数组。而DirectByteBuffer是直接操作操作系统本地代码创建的内存缓冲数组(c、c++的数组)。

由于DirectByteBuffer操作的缓冲区是通过操作系统本地代码创建的,对于java来说创建和销毁DirectByteBuffer更消耗性能。而HeapByteBuffer内部是直接创建的java数组,对于java来说更快。可以根据下面的测试代码测试:
 

public static void directAndHeapSpeedCompare(){
            int length=1000000;
            directExecuteTime(length);
            heapExecuteTime(length);
        }
        private static void directExecuteTime(int length){
            long startTime=System.currentTimeMillis();
            ByteBuffer[] byteBufferArray = new ByteBuffer[length];
            for (int i = 0; i <length ; i++) {
                byteBufferArray[i]=ByteBuffer.allocateDirect(1024);
            }
            long endTime=System.currentTimeMillis();
            System.out.println("创建"+length+"个DirectByteBuffer所消耗的时间:"+(endTime-startTime));
        }
        private static void heapExecuteTime(int length){
            long startTime=System.currentTimeMillis();
            ByteBuffer[] byteBufferArray = new ByteBuffer[length];
            for (int i = 0; i <length ; i++) {
                byteBufferArray[i]=ByteBuffer.allocate(1024);
            }
            long endTime=System.currentTimeMillis();
            System.out.println("创建"+length+"个HeapByteBuffer所消耗的时间:"+(endTime-startTime));
        }

我的测试结果是:

创建1000000个DirectByteBuffer所消耗的时间:1443
创建1000000个HeapByteBuffer所消耗的时间:925

那么为什么创建DirectByteBuffer比HeapByteBuffer性能差却还使用DirectByteBuffer呢?

答:创建DirectByteBuffer的确不如HeapByteBuffer快,但是本地IO(从操作系统本地获取数据,比如文件、socket网络数据)修改数据DirectByteBuffer是更快的。因为:

HeapByteBuffer的缓冲区是java中的java数组,使用HeapByteBuffer读取一个文件,操作系统会先把文件读取到操作系统管理的内存中,然后在把操作系统管理的这块内存的数据复制到jvm管理的内存(即HeapByteBuffer管理的java字节数组)中,然后HeapByteBuffer对java字节数组进行操作。。

而DirectByteBuffer(1)先在操作系统内核所管理的内存缓冲区中(文件系统页)开辟一块内存空间(作为缓冲区),文件数据可以直接从操作系统复制到该缓冲区中(2)用户写入和读取数据就可以直接操作这块缓冲区。。。。比使用HeapByteBuffer少了一个步骤,效率自然提升了。

 

什么情况下使用DirectByteBuffer(ByteBuffer.allocateDirect(int))?

1、频繁的native IO,即缓冲区 中转 从操作系统获取的文件数据、或者使用缓冲区中转网络数据等

2、不需要经常创建和销毁DirectByteBuffer对象

3、经常复用DirectByteBuffer对象,即经常写入数据到DirectByteBuffer中,然后flip,再读取出来,最后clear。。反复使用该DirectByteBuffer对象。

而且,DirectByteBuffer不会占用堆内存。。也就是不会受到堆大小限制,只在DirectByteBuffer对象被回收后才会释放该缓冲区。

什么情况下使用HeapByteBuffer(ByteBuffer.allocate(int))?

1、同一个HeapByteBuffer对象很少被复用,并且该对象经常是用一次就不用了,此时可以使用HeapByteBuffer,因为创建HeapByteBuffer开销比DirectByteBuffer低。(但是!!创建所消耗时间差距只是一倍以下的差距,一般一次只会创建一个DirectByteBuffer对象反复使用,而不会创建几百个DirectByteBuffer,所以在创建一个对象的情况下,HeapByteBuffer并没有什么优势,所以,开发中要使用ByteBuffer时,直接用DirectByteBuffer就行了)

 

总结:

HeapByteBuffer和DirectByteBuffer

1、HeapByteBuffer就是创建效率高,读取和写入的效率低。

2、DirectByteBuffer是创建效率低,读取和写入的效率高。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值