NIO ByteBuffer的allocate与allocateDirect区别(HeapByteBuffer与DirectByteBuffer的区别)
在Java中当我们要对数据进行更底层的操作时,一般是操作数据的字节(byte)形式,这时经常会用到ByteBuffer这样一个类。
ByteBuffer提供了两种静态实例方式:
- public static ByteBuffer allocate(int capacity)
- public static ByteBuffer allocateDirect(int capacity)
为什么要提供两种方式呢?这与Java的内存使用机制有关。
第一种分配方式产生的内存开销是在JVM中的,而另外一种的分配方式产生的开销在JVM之外,也就是系统级的内存分配。
当Java程序接收到外部传来的数据时,首先是被系统内存所获取,然后在由系统内存复制复制到JVM内存中供Java程序使用。
所以在另外一种分配方式中,能够省去复制这一步操作,效率上会有所提高。可是系统级内存的分配比起JVM内存的分配要耗时得多,所以并非不论什么时候allocateDirect的操作效率都是最高的。
以下是一个不同容量情况下两种分配方式的操作时间对照:
![](/assets/blank.gif)
由图能够看出,当操作数据量非常小时,两种分配方式操作使用时间基本是同样的,第一种方式有时可能会更快,可是当数据量非常大时,另外一种方式会远远大于第一种的分配方式。
其中allocateDirect分配的字节缓冲区用中文叫做直接缓冲区(DirectByteBuffer),用allocate分配的ByteBuffer叫做堆字节缓冲区(HeapByteBuffer)..
其实根据类名就可以看出,HeapByteBuffer所创建的字节缓冲区就是在jvm堆中的,即内部所维护的java字节数组。
而DirectByteBuffer是直接操作操作系统本地代码创建的内存缓冲数组(c、c++的数组)。
由于DirectByteBuffer操作的缓冲区是通过操作系统本地代码创建的,对于java来说创建和销毁DirectByteBuffer更消耗性能。
而HeapByteBuffer内部是直接创建的java数组,对于java来说更快。
可以根据下面的测试代码测试:
github源码地址
package NIO_FileChannel;import java.nio.ByteBuffer;public class DirectAndHeapSpeedCompare {public static void main(String[] args) {directAndHeapSpeedCompare();}private static void directAndHeapSpeedCompare() {int length = 10000;heapExecuteTime(length);directExecuteTime(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));}
}
创建10000个HeapByteBuffer所消耗的时间:12
创建10000个DirectByteBuffer所消耗的时间:17
那么为什么创建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是创建效率低,读取和写入的效率高。
NIO ByteBuffer的allocate与allocateDirect区别(HeapByteBuffer与DirectByteBuffer的区别)相关推荐
- NIO ByteBuffer 的 allocate 和 allocateDirect 的区别(HeapByteBuffer 和 DirectByteBuffer 的区别)
ByteBuffer 中 NIO里用得最多的Buffer ,有两种实现方式:HeapByteBuffer基于Java堆的实现,而DirectByteBuffer 使用了 unsafed 的API 进行 ...
- ByteBuffer的allocate和allocateDirect区别
在Java中当我们要对数据进行更底层的操作时,通常是操作数据的字节(byte)形式,这时常常会用到ByteBuffer这样一个类.ByteBuffer提供了两种静态实例方式: public stati ...
- ByteBuffer的allocate和allocateDirect
在Java中当我们要对数据进行更底层的操作时,一般是操作数据的字节(byte)形式,这时经常会用到ByteBuffer这样一个类.ByteBuffer提供了两种静态实例方式: Java代码 pub ...
- ByteBuffer.allocate()与allocateDirect()的区别
allocate()产生的是HeapByteBuffer的实例, 本质上是一个no direct buffer, allocateDirect()产生的是DirectByteBuffer的实例, 本质 ...
- java byte 释放内存_java java.nio.ByteBuffer.allocateDirect 导致内存泄露
java能够经过java.nio.ByteBuffer.allocateDirect(capacity)直接运用non java heap(java堆外)的内存 . 一.运用意图: 1.拓荒数据缓冲区 ...
- java nio rewind_java.nio.ByteBuffer中的flip()、rewind()、compact()等方法的使用和区别
java.nio.ByteBuffer 1. ByteBuffer中的参数position.limit.capacity.mark含义: position:表示当前指针的位置(下一个要操作的数据元素的 ...
- Classloader、NIO ByteBuffer.allocateDirect的回收 、一致性Hash
比较多的东西,写的比较杂乱,以后会写一些自己复习到的内容,或者新学习到的东西,尽量让自己写的东西有价值,对一天学习的内容有一个总结. 一.Classloader 1.过程 1)加载:查找并加载类的二进 ...
- 13. 一步一图带你深入剖析 JDK NIO ByteBuffer 在不同字节序下的设计与实现
一步一图带你深入剖析 JDK NIO ByteBuffer 在不同字节序下的设计与实现 让我们来到微观世界重新认识 Netty 在前面 Netty 源码解析系列 <聊聊 Netty 那些事儿&g ...
- 一步一图带你深入剖析 JDK NIO ByteBuffer 在不同字节序下的设计与实现
让我们来到微观世界重新认识 Netty 在前面 Netty 源码解析系列 <聊聊 Netty 那些事儿>中,笔者带领大家从宏观世界详细剖析了 Netty 的整个运转流程.从一个网络数据包在 ...
最新文章
- 名片DIY官方认证代码_【教程】DIYQQ动态名片
- python启蒙视频_python启蒙阶段
- Python中的numpy.zeros()
- 【个人笔记】OpenCV4 C++ 快速入门 12课
- L1-064 估值一亿的AI核心代码 (20 分)—团体程序设计天梯赛
- Java编程入门基础知识合集
- IDEA的介绍基础运用和优化还有各种功能(超级全!!多图!!)
- matlab判断星期几的语句,计算某一天是星期几的matlab程序
- 电脑公司GHOST WIN7 装机旗舰版 2013 09
- hp计算机如何重装win7,为你解答惠普电脑怎么重装win7系统
- 浏览器 user agent
- 新手如何选择外汇交易平台?
- 如何删除卸载苹果mac电脑应用软件没有残留垃圾
- Java实现将本地.html文件以.docx文件格式导出并添加水印
- python怎么编写口算题_来出口算题—— Python编程
- 浦发银行面试问题总结
- rk3399 android 9.0 frameworks中添加导航栏状态栏控制
- LeetCode刷题(61)~找出数组中的幸运数
- 如何实现,一人账号,全村人(宿舍)无限上网——校园网卡BUG篇-无锡科技职业学院
- C# WFM调用百度地图