java.nio.HeapByteBuffer堆字节缓冲区源码解析

1.ByteBuffer的解析

http://blog.csdn.net/ya_1249463314/article/details/79271333


2.什么是堆字节缓冲区

HeapByteBuffer堆字节缓冲区是将缓冲区分配在jvm中的heap堆上,其实现本身是一个字节数组,实际上就是操作系统中的用户内存,而不是内核内存。


3.所属包

package java.nio;


4.继承与实现关系

class HeapByteBuffer extends ByteBuffer

5.构造器

/**
	 * 指定参数构造器,
	 * 初始化标记mark为-1,设置堆缓冲数组空间大小为cap,字节数组的偏移量为0
	 */
    HeapByteBuffer(int cap, int lim) {            
        super(-1, 0, lim, cap, new byte[cap], 0);
    }

	/**
	 * 指定参数构造器,
	 * 初始化标记mark为-1,设置读写的开始位置为off,读写的最大容量为off+len
	 * 设置缓冲区的最大容量为buf字节数组的容量,设置堆缓冲数组为buf,字节数组的偏移量为0
	 */
    HeapByteBuffer(byte[] buf, int off, int len) { 
        super(-1, off, off + len, buf.length, buf, 0);
    }

	/**
	 * 指定参数构造器,
	 * 初始化标记为mark,设置读写的开始位置为pos,读写的最大容量为lim
	 * 设置缓冲区的最大容量为cap,设置堆缓冲数组为buf,字节数组的偏移量为off
	 */
    protected HeapByteBuffer(byte[] buf,
                                   int mark, int pos, int lim, int cap,
                                   int off)
    {
        super(mark, pos, lim, cap, buf, off);
    }

6.常用方法

/**
	 * 创建新的堆字节缓冲区,其内容是此缓冲区内容的共享子序列
	 * 标记mark为-1,读写开始位置为0,读写的最大容量为缓冲区剩余元素的容量
	 * 缓冲区的最大容量为缓冲区剩余元素的容量,字节数组的偏移量为当前读写位置加上原字节数组的偏移量
	 */
    public ByteBuffer slice() {
        return new HeapByteBuffer(hb,
                                        -1,
                                        0,
                                        this.remaining(),
                                        this.remaining(),
                                        this.position() + offset);
    }

	/**
	 * 创建共享此缓冲区内容的新的堆字节缓冲区
	 * 标记mark为当前的缓冲区的mark,读写的开始位置为当前缓冲区的pos,
	 * 读写的最大容量为当前缓冲区的lim,缓冲区的最大容量为当前缓冲区的最大容量cap
	 * 数组的偏移量为当前数组的偏移量offset
	 */
    public ByteBuffer duplicate() {
        return new HeapByteBuffer(hb,
                                        this.markValue(),
                                        this.position(),
                                        this.limit(),
                                        this.capacity(),
                                        offset);
										
    }

	/**
	 * 创建一个只读的堆字节缓冲区
	 * 标记mark为当前的缓冲区的mark,读写的开始位置为当前缓冲区的pos,
	 * 读写的最大容量为当前缓冲区的lim,缓冲区的最大容量为当前缓冲区的最大容量cap
	 * 数组的偏移量为当前数组的偏移量offset
	 */
    public ByteBuffer asReadOnlyBuffer() {

        return new HeapByteBufferR(hb,
                                     this.markValue(),
                                     this.position(),
                                     this.limit(),
                                     this.capacity(),
                                     offset);
									 
    }

	//设置读取字节数组的偏移量为i+offset
    protected int ix(int i) {
        return i + offset;
    }

	//获取下一个字节
    public byte get() {
        return hb[ix(nextGetIndex())];
    }

	//获取指定下标的字节
    public byte get(int i) {
        return hb[ix(checkIndex(i))];
    }

	//将当前的缓冲区中的字节数组从position加1中开始复制到输入的字节数组dst中
    public ByteBuffer get(byte[] dst, int offset, int length) {
		//检查下标是否越界
        checkBounds(offset, length, dst.length);
		//检查缓冲区是否溢出
        if (length > remaining())
            throw new BufferUnderflowException();
		//将缓冲区中的字节数组的指定位置position+offset开始复制字节到指定的dst字节数组
        System.arraycopy(hb, ix(position()), dst, offset, length);
		//设置读写的开始位置为position+length
        position(position() + length);
		//返回当前的字节缓冲区
        return this;
    }

	//缓冲区是否为直接在内核上缓冲区,返回false,因为现在是在jvm堆字节缓冲区
    public boolean isDirect() {
        return false;
    }

	//缓冲区是否为只读
    public boolean isReadOnly() {
        return false;
    }
	
	//存储字节x到字节缓冲区中,返回字节缓冲区
    public ByteBuffer put(byte x) {
        hb[ix(nextPutIndex())] = x;
        return this;
    }
	
	//将指定字节缓冲区的位置的字节更新为x,返回字节缓冲区
    public ByteBuffer put(int i, byte x) {
        hb[ix(checkIndex(i))] = x;
        return this;
    }

	//将指定的字节数组src的元素存储到当前的字节缓冲区中
    public ByteBuffer put(byte[] src, int offset, int length) {
		//检查下标是否越界
        checkBounds(offset, length, src.length);
		//检查缓冲区是否溢出
        if (length > remaining())
            throw new BufferOverflowException();
		//将输入的字节数组中src从指定偏移量offset开始复制字节到当前的字节缓冲区
        System.arraycopy(src, offset, hb, ix(position()), length);
		//设置当前的字节缓冲区中的读写开始位置为原有的position加上新增的字节数组的length
        position(position() + length);
		//返回当前的字节缓冲区
        return this;
    }

	//将指定的字节缓冲区的字节存储到当前的字节缓冲区
    public ByteBuffer put(ByteBuffer src) {
		//判断src是否为堆字节缓冲区
        if (src instanceof HeapByteBuffer) {
            if (src == this)
                throw new IllegalArgumentException();
			//获取堆字节缓冲区
            HeapByteBuffer sb = (HeapByteBuffer)src;
			//获取字节缓冲区中剩余字节的容量
            int n = sb.remaining();
            if (n > remaining())
                throw new BufferOverflowException();
			//将指定的字节缓冲区的字节复制到当前的字节缓冲区中
            System.arraycopy(sb.hb, sb.ix(sb.position()),
                             hb, ix(position()), n);
			//设置输入的字节缓冲区src的读写开始位置
            sb.position(sb.position() + n);
			//设置当前缓冲区的读写开始位置
            position(position() + n);
        } else if (src.isDirect()) {//判断src是否为直接内核缓冲区
			//获取输入字节缓冲区的字节容量为n
            int n = src.remaining();
            if (n > remaining())
                throw new BufferOverflowException();
			//将指定的字节缓冲区src中的字节写入到当前的字节缓冲区hb
            src.get(hb, ix(position()), n);
			//设置缓冲区中读写的开始位置为position
            position(position() + n);
        } else {
			//将输入的指定缓冲区中的元素转移到另一个缓冲区中  
            super.put(src);
        }
        return this;
    }

	//压缩当前的字节缓冲区
    public ByteBuffer compact() {
		//将当前的缓冲区中的字节数组hb从position+offset开始复制到hb中
        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
		//设置当前的缓冲区中读写的开始位置为字节数组的剩余元素大小
        position(remaining());
		//设置读写的最大容量为当前缓冲区的最大容量
        limit(capacity());
		//设置标记mark为-1
        discardMark();
        return this;
    }

	//获取指定下标的字节
    byte _get(int i) {                          
        return hb[i];
    }

	//将指定下标的字节更新为b
    void _put(int i, byte b) {                  
        hb[i] = b;
    }





  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值