NIO中缓冲区是数据传输的基础,JDK通过ByteBuffer实现,Netty框架中并未采用JDK原生的ByteBuffer,而是构造了ByteBuf。
ByteBuf对ByteBuffer做了大量的优化,比如说内存池,零拷贝,引用计数(不依赖GC),本文主要是分析这些优化,学习这些优化思想,学以致用,在实际工程中,借鉴这些优化方案和思想。
直接内存和堆内存
首先先讲一下这里面需要用的基础知识,在JVM中 内存可分为两大块,一个是堆内存,一个是直接内存。这里简单介绍一下
堆内存:堆内存是Jvm所管理的内存,相比方法区,栈内存,堆内存是最大的一块。所有的对象实例实例以及数组都要在堆上分配。
Java的垃圾收集器是可以在堆上回收垃圾。
直接内存:JVM使用Native函数在堆外分配内存,之后通过Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。直接内存不会受到Java堆的限制,只受本机内存影响。
Java的GC只会在老年区满了触发Full GC时,才会去顺便清理直接内存的废弃对象。
JDK原生缓冲区ByteBuffer在NIO中,所有数据都是用缓冲区处理的。读写数据,都是在缓冲区中进行的。缓存区实质是是一个数组,通常使用字节缓冲区——ByteBuffer。
属性:
属性
说明
capacity
缓冲区的大小,一旦申请将不能改变
position
位置索引,表示读模式或者写模式数据的位置,读模式和写模式切换的时候position会被重置为0,positon最大可谓capacity-1。
limit
在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。读模式下,limit等于buffer的capacity
mark
标记,指一个备忘位置,调用mark()来设定mark=position,调用reset()来设定postion=mark,标记未设定前是未定义的.
使用方式:
ByteBuffer可以申请两种方式的内存,分别为堆内存和直接内存,首先看申请堆内存。
// 申请堆内存 ByteBuffer HeapbyteBuffer = ByteBuffer.allocate(1024);