ByteBuffer 中 NIO里用得最多的Buffer ,有两种实现方式:HeapByteBuffer基于Java堆的实现,而DirectByteBuffer 使用了 unsafed 的API 进行了对外的实现。

ByteBuffer 提供了两种静态实例方式,分别为:

//1.
public static ByteBuffer allocate(int capacity) {if (capacity < 0)throw new IllegalArgumentException();return new HeapByteBuffer(capacity, capacity);
}//2.
public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);
}

提供两种方式是与Java的内存使用机制有关

代码中第一种方式:产生的内存开销是在 JVM 中的

    HeapByteBuffer(int cap, int lim) {            // package-privatesuper(-1, 0, lim, cap, new byte[cap], 0);/*hb = new byte[cap];offset = 0;*/}

第二种方式:开销在JVM之外,也就是 系统级 的内存分配  (VM.isDirectMemoryPageAligned())

DirectByteBuffer(int cap) {                   // package-privatesuper(-1, 0, cap, cap);boolean pa = VM.isDirectMemoryPageAligned();int ps = Bits.pageSize();long size = Math.max(1L, (long)cap + (pa ? ps : 0));Bits.reserveMemory(size, cap);long base = 0;try {base = unsafe.allocateMemory(size);} catch (OutOfMemoryError x) {Bits.unreserveMemory(size, cap);throw x;}unsafe.setMemory(base, size, (byte) 0);if (pa && (base % ps != 0)) {// Round up to page boundaryaddress = base + ps - (base & (ps - 1));} else {address = base;}cleaner = Cleaner.create(this, new Deallocator(base, size, cap));att = null;
}

当Java程序接收到外部传来的数据时,首先被系统内存所获取,然后在系统内存复制 到JVM 内存中供java使用。

所以在另一种分配方式中,能够省去复制这一步的操作,效率上有所提高。但是系统级别内存的分配比JVM内存的分配要耗时多。所以并非不论什么时候 allocateDirect的操作效率都是很高的。

下面分享不同容量下两种分类时间的对照:

根据上图看出,当操作的数据量小时,两种分配方式几乎是一样的,第一种方式会更快点,但是当数据量大的时候,另一种方式会远远大于第一种的分配方式

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

其实根据类名就可以看出,HeapByteBuffer所创建的字节缓冲区就是在jvm堆中的,即内部所维护的java字节数组。

而DirectByteBuffer是直接操作操作系统本地代码创建的内存缓冲数组(c、c++的数组)。

由于DirectByteBuffer操作的缓冲区是通过操作系统本地代码创建的,对于java来说创建和销毁DirectByteBuffer更消耗性能。

而HeapByteBuffer内部是直接创建的java数组,对于java来说更快。

可以根据下面的测试代码测试:

import java.nio.ByteBuffer;public class DirectAndHeapSpeedCompare {public static void main(String[] args) {directExecuteTime(100000);heapExecuteTime(100000);}public static void directExecuteTime(int length) {long startTime = System.currentTimeMillis();ByteBuffer[] buffer = new ByteBuffer[length];for (int i = 0; i < length; i++) {buffer[i] = ByteBuffer.allocateDirect(1024);}long endTime = System.currentTimeMillis();System.out.println("创建:" + length + "个directExecuteTime需要耗时:" + (endTime - startTime));}public static void heapExecuteTime(int length) {long startTime = System.currentTimeMillis();ByteBuffer[] buffer = new ByteBuffer[length];for (int i = 0; i < length; i++) {buffer[i] = ByteBuffer.allocate(1024);}long endTime = System.currentTimeMillis();System.out.println("创建:" + length + "个heapExecuteTime需要耗时:" + (endTime - startTime));}}

控制台显示日志为:

创建:100000个directExecuteTime需要耗时:64
创建:100000个heapExecuteTime需要耗时:135

那么为什么创建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 的区别)相关推荐

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

    在Java中当我们要对数据进行更底层的操作时,一般是操作数据的字节(byte)形式,这时经常会用到ByteBuffer这样一个类. ByteBuffer提供了两种静态实例方式: public stat ...

  2. ByteBuffer的allocate和allocateDirect区别

    在Java中当我们要对数据进行更底层的操作时,通常是操作数据的字节(byte)形式,这时常常会用到ByteBuffer这样一个类.ByteBuffer提供了两种静态实例方式: public stati ...

  3. ByteBuffer的allocate和allocateDirect

    在Java中当我们要对数据进行更底层的操作时,一般是操作数据的字节(byte)形式,这时经常会用到ByteBuffer这样一个类.ByteBuffer提供了两种静态实例方式: Java代码   pub ...

  4. java byte 释放内存_java java.nio.ByteBuffer.allocateDirect 导致内存泄露

    java能够经过java.nio.ByteBuffer.allocateDirect(capacity)直接运用non java heap(java堆外)的内存 . 一.运用意图: 1.拓荒数据缓冲区 ...

  5. java nio rewind_java.nio.ByteBuffer中的flip()、rewind()、compact()等方法的使用和区别

    java.nio.ByteBuffer 1. ByteBuffer中的参数position.limit.capacity.mark含义: position:表示当前指针的位置(下一个要操作的数据元素的 ...

  6. Classloader、NIO ByteBuffer.allocateDirect的回收 、一致性Hash

    比较多的东西,写的比较杂乱,以后会写一些自己复习到的内容,或者新学习到的东西,尽量让自己写的东西有价值,对一天学习的内容有一个总结. 一.Classloader 1.过程 1)加载:查找并加载类的二进 ...

  7. 13. 一步一图带你深入剖析 JDK NIO ByteBuffer 在不同字节序下的设计与实现

    一步一图带你深入剖析 JDK NIO ByteBuffer 在不同字节序下的设计与实现 让我们来到微观世界重新认识 Netty 在前面 Netty 源码解析系列 <聊聊 Netty 那些事儿&g ...

  8. 一步一图带你深入剖析 JDK NIO ByteBuffer 在不同字节序下的设计与实现

    让我们来到微观世界重新认识 Netty 在前面 Netty 源码解析系列 <聊聊 Netty 那些事儿>中,笔者带领大家从宏观世界详细剖析了 Netty 的整个运转流程.从一个网络数据包在 ...

  9. java.nio.ByteBuffer用法小结

    转载自  java.nio.ByteBuffer用法小结 在NIO中,数据的读写操作始终是与缓冲区相关联的.读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入 ...

最新文章

  1. 在Python3.4中实现opencv3.1.0的安装配置
  2. Kubernetes + CRI + Kata + Firecracker
  3. Login failed with an access denied error.
  4. ES6 中 Promise 详解
  5. oracle判断侦听状态,oracle 监听状态为BLOCKED
  6. 聚类 K-Means Using Python
  7. [C++] 井字棋游戏源码
  8. Mysql修改存储过程相关权限问题
  9. 一个程序详细研究DataReader(转)
  10. 使用arpspoof实现内网ARP欺骗
  11. LogMeIn远程控制
  12. 文本居中对齐(CSS、HTML)
  13. R语言机器学习:xgboost的使用及其模型解释
  14. 设置全屏代码android,Android实现全屏显示的方法
  15. Sentinel 哨兵 实现redis高可用
  16. three.js 文本_使用Three-bmfont-text在Three.js中创建文本
  17. 堆栈callstack打印
  18. 国外优秀JAVA技术网站推荐
  19. CATIA二次开发—参数那点事
  20. 高手速成android开源项目[View篇]

热门文章

  1. 泰坦尼克号生还情况数据分析
  2. PowerDesigne实用小例子(适合初学者)
  3. 小白学opengl之glpushmatrix()与glpopmatrix()的作用
  4. 工业以太网到底有什么类型
  5. Apache HTTP 下载和安装
  6. 前端css实现最基本的时间轴
  7. 基于LM358运放的电压跟随器仿真
  8. Vulnhub靶机:HARRYPOTTER_ NAGINI
  9. 部署在阿里云服务器上的系统也要做等保测评吗?
  10. 从广州到长沙,聊聊我的码农之路