文档章节

java.nio.ByteBuffer源码解读

A__17
 A__17
发布于 2017/08/21 23:04
字数 2008
阅读 2
收藏 0

版本:JDK7

package java.nio;

public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> {

// These fields are declared here rather than in Heap-X-Buffer in order to
// reduce the number of virtual method invocations needed to access these
// values, which is especially costly when coding small buffers.
//
final byte[] hb;                  // Non-null only for heap buffers
final int offset;
boolean isReadOnly;                 // Valid only for heap buffers


ByteBuffer(int mark, int pos, int lim, int cap, byte[] hb, int offset) {
    super(mark, pos, lim, cap);
    this.hb = hb;
    this.offset = offset;
}

ByteBuffer(int mark, int pos, int lim, int cap) { // package-private
    this(mark, pos, lim, cap, null, 0);
}


// 创建一个容量为capacity的ByteBuffer对象
public static ByteBuffer allocateDirect(int capacity) {
    return new DirectByteBuffer(capacity);
}


// 创建一个容量为capacity的ByteBuffer对象
public static ByteBuffer allocate(int capacity) {
    if (capacity < 0) throw new IllegalArgumentException();
    return new HeapByteBuffer(capacity, capacity);
}


public static ByteBuffer wrap(byte[] array, int offset, int length) {
    try {
        return new HeapByteBuffer(array, offset, length);
    } catch (IllegalArgumentException x) {
        throw new IndexOutOfBoundsException();
    }
}

public static ByteBuffer wrap(byte[] array) {
    return wrap(array, 0, array.length);
}

public abstract ByteBuffer slice();
public abstract ByteBuffer duplicate();
public abstract ByteBuffer asReadOnlyBuffer();

/**
 * Reads the byte at this buffer's position, and then increments the position.
 */
// 读取单个字节,并将position自增1
public abstract byte get();

/**
 * Writes the given byte into this buffer at the current position, and then increments the position. 
 */
// 将给定的单个字节写入缓冲区的当前位置,并将position自增1
public abstract ByteBuffer put(byte b);


// 读取指定位置的字节,注意:不会改变position
public abstract byte get(int index);

// 将给定的单个字节写入缓冲区的index位置,注意:不会改变position
public abstract ByteBuffer put(int index, byte b);


// -- Bulk get operations --
/**
 * This method transfers bytes from this buffer into the given destination array. 
 */
// (从Buffer中)读取多个字节(从索引offset开始,读取length长度的数据)到dst中,如果Buffer剩余的空间小于length,则抛异常
public ByteBuffer get(byte[] dst, int offset, int length) {
    checkBounds(offset, length, dst.length);
    if (length > remaining())
        throw new BufferUnderflowException();
    int end = offset + length;
    for (int i = offset; i < end; i++)
        dst[i] = get();
    return this;
}

/**
 * This method transfers bytes from this buffer into the given destination array.
 */
// 批量读取dst.length个字节到dst中,如果Buffer剩余的空间小于dst的length,则抛异常
public ByteBuffer get(byte[] dst) {
    return get(dst, 0, dst.length);
}

// -- Bulk put operations --
/**
 * 将src中的数据写入Buffer的当前位置
 */
public ByteBuffer put(ByteBuffer src) {
    if (src == this)
        throw new IllegalArgumentException();
    int n = src.remaining();
    if (n > remaining())
        throw new BufferOverflowException();
    for (int i = 0; i < n; i++)
        put(src.get());
    return this;
}

public ByteBuffer put(byte[] src, int offset, int length) {
    checkBounds(offset, length, src.length);
    if (length > remaining())
        throw new BufferOverflowException();
    int end = offset + length;
    for (int i = offset; i < end; i++)
        this.put(src[i]);
    return this;
}

public final ByteBuffer put(byte[] src) {
    return put(src, 0, src.length);
}


// -- Other stuff --

/**
 * Tells whether or not this buffer is backed by an accessible byte array.
 *
 * <p> If this method returns <tt>true</tt> then the {[@link](https://my.oschina.net/u/393) #array() array}
 * and {[@link](https://my.oschina.net/u/393) #arrayOffset() arrayOffset} methods may safely be invoked.
 * </p>
 *
 * [@return](https://my.oschina.net/u/556800)  <tt>true</tt> if, and only if, this buffer
 *          is backed by an array and is not read-only
 */
public final boolean hasArray() {
    return (hb != null) && !isReadOnly;
}

/**
 * Returns the byte array that backs this
 * buffer  <i>(optional operation)</i>.
 *
 * <p> Modifications to this buffer's content will cause the returned
 * array's content to be modified, and vice versa.
 *
 * <p> Invoke the {[@link](https://my.oschina.net/u/393) #hasArray hasArray} method before invoking this
 * method in order to ensure that this buffer has an accessible backing
 * array.  </p>
 *
 * [@return](https://my.oschina.net/u/556800)  The array that backs this buffer
 *
 * @throws  ReadOnlyBufferException
 *          If this buffer is backed by an array but is read-only
 *
 * @throws  UnsupportedOperationException
 *          If this buffer is not backed by an accessible array
 */
public final byte[] array() {
    if (hb == null) throw new UnsupportedOperationException();
    if (isReadOnly) throw new ReadOnlyBufferException();
    return hb;
}

/**
 * Returns the offset within this buffer's backing array of the first
 * element of the buffer  <i>(optional operation)</i>.
 *
 * <p> If this buffer is backed by an array then buffer position <i>p</i>
 * corresponds to array index <i>p</i> + <tt>arrayOffset()</tt>.
 *
 * <p> Invoke the {@link #hasArray hasArray} method before invoking this
 * method in order to ensure that this buffer has an accessible backing
 * array.  </p>
 *
 * @return  The offset within this buffer's array
 *          of the first element of the buffer
 *
 * @throws  ReadOnlyBufferException
 *          If this buffer is backed by an array but is read-only
 *
 * @throws  UnsupportedOperationException
 *          If this buffer is not backed by an accessible array
 */
public final int arrayOffset() {
    if (hb == null) throw new UnsupportedOperationException();
    if (isReadOnly) throw new ReadOnlyBufferException();
    return offset;
}

/**
 * Compacts this buffer. 压缩并整理Buffer。
 *
 * The bytes between the buffer's current position and its limit, if any, are copied to the beginning of the buffer.
 * That is, the byte at index p=position() is copied to index zero, 
 * the byte at index p+1 is copied to index one, 
 * and so forth until the byte at index limit()-1 is copied to index n=limit()-1-p 
 * The buffer's position is then set to n+1 and its limit is set to its capacity.  The mark, if defined, is discarded.
 * 
 * 即:将所有未读的数据拷贝到Buffer的起始处,然后将position设到最后一个未读元素的后面
 * limit设置为capacity,此时,如果向Buffer中写数据,则不会覆盖之前未读的数据!
 * 与clear()方法的比较:
 * 		如果Buffer中存在未读的数据,调用clear()方法后,这些未读的数据将会被“遗忘”,因为在clear之后,position的值为0,故无法确定未读数据的位置。
 */
public abstract ByteBuffer compact();

/**
 * Tells whether or not this byte buffer is direct. </p>
 */
public abstract boolean isDirect();


public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append(getClass().getName());
    sb.append("[pos=");
    sb.append(position());
    sb.append(" lim=");
    sb.append(limit());
    sb.append(" cap=");
    sb.append(capacity());
    sb.append("]");
    return sb.toString();
}

/**
 * Returns the current hash code of this buffer.
 */
public int hashCode() {
    int h = 1;
    int p = position();
    for (int i = limit() - 1; i >= p; i--)
        h = 31 * h + (int)get(i);
    return h;
}

/**
 * Tells whether or not this buffer is equal to another object.
 *
 * They have the same element type,
 * They have the same number of remaining elements,
 * and The two sequences of remaining elements, 
 * considered independently of their starting positions, are pointwise equal.
 * 
 * 即:Buffer中元素的类型相同,并且剩余的元素完全相同,则返回true
 * 注意:并不是比较Buffer的所有数据,只是比较Buffer中的剩余数据。
 */
public boolean equals(Object ob) {
    if (this == ob)
        return true;
    if (!(ob instanceof ByteBuffer))
        return false;
    ByteBuffer that = (ByteBuffer)ob;
    if (this.remaining() != that.remaining())
        return false;
    int p = this.position();
    for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
        if (!equals(this.get(i), that.get(j)))
            return false;
    return true;
}

private static boolean equals(byte x, byte y) {
    return x == y;
}

/**
 * Compares this buffer to another.
 *
 * 比较两个Buffer的剩余元素
 * 一个Buffer“小于”另一个Buffer的场景:
 * 		第一个不相等的元素小于另一个Buffer中对应的元素
 * 		所有元素都相等,但是第一个Buffer的元素个数小于另一个Buffer的个数
 */
public int compareTo(ByteBuffer that) {
    int n = this.position() + Math.min(this.remaining(), that.remaining());
    for (int i = this.position(), j = that.position(); i < n; i++, j++) {
        int cmp = compare(this.get(i), that.get(j));
        if (cmp != 0)
            return cmp;
    }
    return this.remaining() - that.remaining();
}

private static int compare(byte x, byte y) {
    return Byte.compare(x, y);
}

// -- Other char stuff --

// -- Other byte stuff: Access to binary data --


boolean bigEndian = true;                                  // package-private
    
boolean nativeByteOrder = (Bits.byteOrder() == ByteOrder.BIG_ENDIAN);	// package-private
   

/**
 * Retrieves this buffer's byte order.
 *
 * <p> The byte order is used when reading or writing multibyte values, and
 * when creating buffers that are views of this byte buffer.  The order of
 * a newly-created byte buffer is always {@link ByteOrder#BIG_ENDIAN
 * BIG_ENDIAN}.  </p>
 *
 * @return  This buffer's byte order
 */
public final ByteOrder order() {
    return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
}

/**
 * Modifies this buffer's byte order.  </p>
 *
 * @param  bo
 *         The new byte order,
 *         either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
 *         or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
 *
 * @return  This buffer
 */
public final ByteBuffer order(ByteOrder bo) {
    bigEndian = (bo == ByteOrder.BIG_ENDIAN);
    nativeByteOrder = (bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN));
    return this;
}

// Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
//
abstract byte _get(int i);                          // package-private
abstract void _put(int i, byte b);                  // package-private


/**
 * Relative <i>get</i> method for reading an int value.
 *
 * <p> Reads the next four bytes at this buffer's current position,
 * composing them into an int value according to the current byte order,
 * and then increments the position by four.  </p>
 *
 * @return  The int value at the buffer's current position
 *
 * @throws  BufferUnderflowException
 *          If there are fewer than four bytes
 *          remaining in this buffer
 */
public abstract int getInt();

/**
 * Relative <i>put</i> method for writing an int
 * value  <i>(optional operation)</i>.
 *
 * <p> Writes four bytes containing the given int value, in the
 * current byte order, into this buffer at the current position, and then
 * increments the position by four.  </p>
 *
 * @param  value
 *         The int value to be written
 *
 * @return  This buffer
 *
 * @throws  BufferOverflowException
 *          If there are fewer than four bytes
 *          remaining in this buffer
 *
 * @throws  ReadOnlyBufferException
 *          If this buffer is read-only
 */
public abstract ByteBuffer putInt(int value);

/**
 * Absolute <i>get</i> method for reading an int value.
 *
 * <p> Reads four bytes at the given index, composing them into a
 * int value according to the current byte order.  </p>
 *
 * @param  index
 *         The index from which the bytes will be read
 *
 * @return  The int value at the given index
 *
 * @throws  IndexOutOfBoundsException
 *          If <tt>index</tt> is negative
 *          or not smaller than the buffer's limit,
 *          minus three
 */
public abstract int getInt(int index);

/**
 * Absolute <i>put</i> method for writing an int
 * value  <i>(optional operation)</i>.
 *
 * <p> Writes four bytes containing the given int value, in the
 * current byte order, into this buffer at the given index.  </p>
 *
 * @param  index
 *         The index at which the bytes will be written
 *
 * @param  value
 *         The int value to be written
 *
 * @return  This buffer
 *
 * @throws  IndexOutOfBoundsException
 *          If <tt>index</tt> is negative
 *          or not smaller than the buffer's limit,
 *          minus three
 *
 * @throws  ReadOnlyBufferException
 *          If this buffer is read-only
 */
public abstract ByteBuffer putInt(int index, int value);

/**
 * Creates a view of this byte buffer as an int buffer.
 *
 * <p> The content of the new buffer will start at this buffer's current
 * position.  Changes to this buffer's content will be visible in the new
 * buffer, and vice versa; the two buffers' position, limit, and mark
 * values will be independent.
 *
 * <p> The new buffer's position will be zero, its capacity and its limit
 * will be the number of bytes remaining in this buffer divided by
 * four, and its mark will be undefined.  The new buffer will be direct
 * if, and only if, this buffer is direct, and it will be read-only if, and
 * only if, this buffer is read-only.  </p>
 *
 * @return  A new int buffer
 */
public abstract IntBuffer asIntBuffer();

// ...

}

© 著作权归作者所有

共有 人打赏支持
A__17
粉丝 2
博文 100
码字总数 117532
作品 0
朝阳
私信 提问
rocketmq源码解析之mqclient启动 codec

rocketmq源码解析之mqclient启动 codec 上次介绍到这个方法org.apache.rocketmq.tools.admin.DefaultMQAdminExtImpl#star,下面介绍mqclient启动源码实现 //启动mqclientmqClientInstance.st......

天河2018
11/01
0
0
Android6.0源码解读之Activity点击事件分发机制

本篇博文是Android点击事件分发机制系列博文的第四篇,主要是从解读Activity类的源码入手,根据源码理清Activity点击事件分发原理,并掌握Activity点击事件分法机制。特别声明的是,本源码解...

mynameishuangshuai
2016/10/23
0
0
spark2.1.0之源码分析——RPC传输管道处理器详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beliefer/article/details/81326016 提示:阅读本文前最好先阅读: 《Spark2.1.0之内置RPC框架》 《spark2.1....

泰山不老生
08/01
0
0
Android6.0源码解读之View点击事件分发机制

本篇博文是Android点击事件分发机制系列博文的第二篇,主要是从解读View类的源码入手,根据源码理清View点击事件分发原理,并掌握View点击事件分法机制。特别声明的是,本源码解读是基于最新...

mynameishuangshuai
2016/10/23
0
0
PerfMa给OpenJDK社区提交的第一个Patch

概述 前两天给openjdk gc-dev的email list提交了一个问题,主要是针对Full GC之后,GC日志里Metaspace的大小在GC前后都一直不变的问题,我在邮件里大概也提了下如何修复该问题,以及猜测了下...

你假笨
09/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

js垃圾回收机制和引起内存泄漏的操作

JS的垃圾回收机制了解吗? Js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。 JS中最常见的垃圾回收方式是标记清除。 工作原理:是当变量进入环境时,将这个变量标记为“...

Jack088
昨天
17
0
大数据教程(10.1)倒排索引建立

前面博主介绍了sql中join功能的大数据实现,本节将继续为小伙伴们分享倒排索引的建立。 一、需求 在很多项目中,我们需要对我们的文档建立索引(如:论坛帖子);我们需要记录某个词在各个文...

em_aaron
昨天
25
0
"errcode": 41001, "errmsg": "access_token missing hint: [w.ILza05728877!]"

Postman获取微信小程序码的时候报错, errcode: 41001, errmsg: access_token missing hint 查看小程序开发api指南,原来access_token是直接当作parameter的(写在url之后),scene参数一定要...

两广总督bogang
昨天
31
0
MYSQL索引

索引的作用 索引类似书籍目录,查找数据,先查找目录,定位页码 性能影响 索引能大大减少查询数据时需要扫描的数据量,提高查询速度, 避免排序和使用临时表 将随机I/O变顺序I/O 降低写速度,占用磁...

关元
昨天
13
0
撬动世界的支点——《引爆点》读书笔记2900字优秀范文

撬动世界的支点——《引爆点》读书笔记2900字优秀范文: 作者:挽弓如月。因为加入火种协会的读书活动,最近我连续阅读了两本论述流行的大作,格拉德威尔的《引爆点》和乔纳伯杰的《疯传》。...

原创小博客
昨天
35
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部