Java 学习系列:ByteBuffer

原创 2016年06月01日 18:39:02

ByteBuffer是Java系统提供的用于字节缓冲区之用的一个基于堆外内存实现的数据结构。在NIO中,无论是读取数据还是写入数据都需要经过ByteBuffer缓冲区做一次中转。


1 . ByteBuffer 的创建方式

ByteBuffer.allocate(1024);
new HeapByteBuffer(capacity, capacity);
ByteBuffer.allocateDirect(1024);
new DirectByteBuffer(capacity);

2 . ByteBuffer 的工作原理?
ByteBuffer 内部是采用一个字节数组来保存读与写的数据的,另外还有其他四个重要的指针参数,

mark <= position <= limit <= capacity

private int mark = -1; //一个标志量,可以暂存我们的读进度(读-写-读)
private int position = 0; //当前正读到或者写到的位置,会随着读写操作而自增
private int limit; //数据装载到的位置,读与写都不能超过此下标
private int capacity; //缓存区的容量

先看一个,先写入数据再读取的过程,
这里写图片描述
调用flip方法后,我们就结束了写模式,转为读模式,position被置为0,从第一个字符开始读取。
会发现这种切换太不灵活,必须读完或者写完才能进行对立的操作,因此这里就需要mark上场了,它可以暂存我们读的位置,然后再进行几步操作,a,获取到limit把position置为limit的值,b,再把limit置为capacity的值,此时可以继续往里面写入一定的数据,最后再通过 reset 把房子mark里的值赋给position,继续进行读操作。

相关扩展
|. 使用堆外内存有哪些好处呢?
理论上能减少GC暂停时间,使用对象池也具有这样的好处。
可以扩展至更大的内存空间。比如超过1TB甚至比主存还大的空间。
可以在进程间共享,减少JVM间的对象复制,使得JVM的分割部署更容易实现。
它的持久化存储可以支持快速重启,同时还能够在测试环境中重现生产数据。
站在系统设计的角度来看,使用堆外内存可以为你的设计提供更多可能。最重要的提升并不在于性能,而是决定性的。

||. 关于应用程序使用堆内内存的工作流程
这里写图片描述
首先,数据会加载到内核缓冲区,也就是第1步
然后又会将内容从内核缓冲区拷贝到用户态的缓冲区,也就是java这里的堆内存了,第2步
我们java调用send,发送的时候,再拷贝到内核缓冲区,第3步
最后再写入目标缓冲,比如网卡,第4步

read() 引入了一次从user mode到kernel mode的上下文切换。实际上调用了sys_read() 来从文件中读取data。第一次copy由DMA完成,将文件内容从disk读出,存储在kernel的buffer中。
然后data被copy到user buffer中,此时read()成功返回。这是触发了第二次context switch: 从kernel到user。至此,数据存储在user的buffer中。
send() socket call 带来了第三次context switch,这次是从user mode到kernel mode。同时,也发生了第三次copy:把data放到了kernel adress space中。当然,这次的kernel buffer和第一步的buffer是不同的两个buffer。
最终 send() system call 返回了,同时也造成了第四次context switch。同时第四次copy发生,DMA将data从kernel buffer拷贝到protocol engine中。第四次copy是独立而且异步的。

如果直接操作JVM的堆外内存,就可以省略掉2,3步,效率高哈

版权声明:本文为博主原创文章,欢迎转载与采用。

thinking in java学习之nio-bytebuffer4

bytebuffer有四个属性 1、position : 当前读取的位置;调用position()时获取;调用get()方法时指向读取位置的下一位;调用put()时指向当前写入的位置的下一位...

[JAVA学习笔记-60]ByteBuffer的分配方式的比较

public static ByteBuffer allocate(int capacity)   public static ByteBuffer allocateDirect(int capac...

Java 学习笔记之 ByteBuffer

在NIO中,数据的读写操作始终是与缓冲区相关联的.读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区.缓冲区是定长的,基本上它只是一个列表,它的所有元素...

Java NIO学习笔记之二-图解ByteBuffer

概述使用ByteBuffer内部字段byte[] buffpositionmarkcapacitylimit图解putflipgetclear Java NIO学习笔记之...

Java NIO学习笔记之二-图解ByteBuffer

yteBuffer前前后后看过好几次了,实际使用也用了一些,总觉得条理不够清晰。 《程序员的思维修炼》一本书讲过,主动学习,要比单纯看资料效果来的好,所以干脆写个详细点的文章来记录一下。 概述...

Java NIO学习笔记之二-图解ByteBuffer

目录:[ - ] 概述使用ByteBuffer内部字段byte[] buffpositionmarkcapacitylimit图解putflipgetclear ByteBuffer前前后后看过...
  • Baple
  • Baple
  • 2013年10月15日 14:01
  • 23679

Java NIO 学习笔记 - ByteBuffer

在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,都是将它放到缓冲区中。缓冲区实质上是一个数组。通...

转载:Java NIO 学习笔记 - ByteBuffer

在 nio 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 nio 中的数据,都是将它放到缓冲区中。缓冲区实质上是一个数组。通...

Java NIO学习笔记之二-图解ByteBuffer

概述 使用 ByteBuffer内部字段 byte[] buff position mark capacity limit 图解 put flip get clear ...

【Java8源码分析】NIO包-Buffer类:ByteBuffer与HeapByteBuffer(一)

转载请注明出处: 1 概述 Java NIO 由以下几个核心部分组成: Buffer Channel Selectors 相关类的使用方法可以参考Java NIO 系列教程...
  • linxdcn
  • linxdcn
  • 2017年06月07日 22:31
  • 768
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java 学习系列:ByteBuffer
举报原因:
原因补充:

(最多只允许输入30个字)