java nio ByteBuffer源码分析

目录

简介

字段hb,offset,isReadOnly,2个构造函数

方法allocateDirect,allocate,2个wrap,slice,duplicate,asReadOnlyBuffer

方法4个get,5个put

方法array,arrayOffset,compact,isDirect,toString,hashCode,2个equals,compareTo

字段bigEndian,nativeByteOrder,方法order,_get,_put

方法getXXX,putXXX,asXXXBuffer(char,short,int,long,float,double)


简介

package java.nio;

/**
 * 字节缓冲区。
 *
 * <p>
 * 此类在字节缓冲区上定义了六类操作:
 *
 * <ul>
 *
 * <li>
 * <p>
 * 读写单个字节的绝对和相对get和put方法;
 * </p>
 * </li>
 *
 * <li>
 * <p>
 * 将连续字节序列从该缓冲区传输到数组中的相对批量get(byte[])方法;
 * </p>
 * </li>
 *
 * <li>
 * <p>
 * 将连续字节序列从字节数组或其他字节缓冲区传输到该缓冲区的相对批量put(byte[])方法;
 * </p>
 * </li>
 *
 *
 * <li>
 * <p>
 * 绝对和相对getChar和putChar方法等,用于读取和写入其他原始类型的值,并以特定字节顺序在字节序列之间进行转换;
 * </p>
 * </li>
 *
 * <li>
 * <p>
 * 创建视图缓冲区的方法,允许将字节缓冲区视为包含其他某种原始类型值的缓冲区;以及
 * </p>
 * </li>
 *
 *
 * <li>
 * <p>
 * 压缩、复制和切片字节缓冲区的方法。
 * </p>
 * </li>
 *
 * </ul>
 *
 * <p>
 * 字节缓冲区可以通过allocate(为缓冲区的内容分配空间)来创建,
 *也可以通过wrap(byte[]),将现有的字节数组包装到缓冲区来创建。
 *
 * <a name="direct"></a>
 * <h2>直接缓冲区与非直接缓冲区</h2>
 *
 * <p>
 * 字节缓冲区可以是直接缓冲区,也可以是非直接缓冲区。
 * 给定一个直接字节缓冲区,Java虚拟机将尽最大努力直接在其上执行I/O操作。
 * 也就是说,它将尝试避免在每次调用底层操作系统的本地IO操作,之前或之后,
 * 将缓冲区的内容复制到,或从,中间缓存区。
 * 
 *
 * <p>
 * 直接字节缓冲区可以通过调用此类的allocateDirect(int)工厂方法来创建。
 * 此方法返回的缓冲区通常比非直接缓冲区具有更高的分配和释放成本。
 * 直接缓冲区的内容可能位于普通垃圾收集堆之外,因此它们对应用程序内存占用的影响可能并不明显。
 * 因此,建议将直接缓冲区主要分配给大型、长寿命的缓冲区,这些缓冲区受底层系统本机I/O操作的影响。
 * 一般来说,只有当直接缓冲区在程序性能上获得可测量的增益时,才最好分配直接缓冲区。
 *
 * <p>
 * 直接字节缓冲区也可以通过FileChannel的map方法,映射文件的一个区域到内存。
 * Java平台的实现可以选择支持通过JNI从本机代码创建直接字节缓冲区。
 * 如果其中一种缓冲区的实例引用了内存的不可访问区域,则尝试访问该区域
 * 不会更改缓冲区的内容,并将导致在访问时或稍后某个时间引发未指定的异常。
 *
 * <p>
 * 字节缓冲区是直接的还是非直接的,可以通过调用它的isDirect方法来确定。
 * 提供此方法是为了在性能关键代码中执行显式缓冲区管理。
 *
 *
 * <a name="bin"></a>
 * <h2>访问二进制数据</h2>
 *
 * <p>
 * 这个类定义了读取和写入除boolean之外的所有其他基元类型的值的方法。
 * 基本类型值根据缓冲区的当前字节顺序,转换为(或从)字节序列,这些字节序列可以通过order方法进行检索和修改。
 * 特定字节顺序由ByteOrder类的实例表示。初始字节的顺序始终是BIG_ENDIAN。
 *
 * <p>
 * 为了访问异构二进制数据,即不同类型的值序列,
 * 此类为每种类型定义了一系列绝对和相对的get和put方法。
 * 例如,对于32位浮点值,此类定义:
 *
 * <blockquote>
 * 
 * <pre>
 * float  {@link #getFloat()}
 * float  {@link #getFloat(int) getFloat(int index)}
 *  void  {@link #putFloat(float) putFloat(float f)}
 *  void  {@link #putFloat(int,float) putFloat(int index, float f)}
 * </pre>
 * 
 * </blockquote>
 *
 * <p>
 * 为char、short、int、long和double类型定义了相应的方法。
 * 绝对get和put方法的参数index是以字节为单位的,而不是被读取或写入的类型。
 *
 * <a name="views"></a>
 *
 * <p>
 * 对于同一类型的数据,这个类定义了即根据给定的字节缓冲区,创建视图的方法。
 * 视图缓冲区只是另一个其内容由字节缓冲区支持的缓冲区。
 * 对字节缓冲区内容的更改将在视图缓冲区中可见,反之亦然;
 * 两个缓冲区的位置、限制和标记值是独立的。
 * 例如,asFloatBuffer方法,创建FloatBuffer类的一个实例,该实例由该方法所在的字节缓冲区支持调用。
 * 对应视图创建方法是为char、short、int、long和double类型定义的。
 *
 * <p>
 * 与类型特定的get和put方法系列相比,视图缓冲区有三个重要优势:
 *
 * <ul>
 *
 * <li>
 * <p>
 * 视图缓冲区的索引不是根据字节,而是根据其值的类型特定大小;
 * </p>
 * </li>
 *
 * <li>
 * <p>
 * 视图缓冲区提供相对批量获取和放置方法,
 * 可以在缓冲区和数组或其他同类缓冲区之间传输连续的值序列;以及
 * </p>
 * </li>
 *
 * <li>
 * <p>
 * 如果它是直接缓冲区,那么它的直接缓冲区可能更有效。
 * </p>
 * </li>
 *
 * </ul>
 *
 * <p>
 * 视图缓冲区的字节顺序固定为创建视图时其字节缓冲区的字节顺序。
 * </p>
 *
 * <h2>引用链</h2>
 *
 * <p>
 * 该类中不需要返回值的方法被指定为返回调用它们的缓冲区。
 * 这允许方法调用被链接。
 * 
 * 语句序列
 * 
 * <blockquote>
 * 
 * <pre>
 * bb.putInt(0xCAFEBABE);
 * bb.putShort(3);
 * bb.putShort(45);
 * </pre>
 * 
 * </blockquote>
 *
 * can, for example, be replaced by the single statement
 *
 * <blockquote>
 * 
 * <pre>
 * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);
 * </pre>
 * 
 * </blockquote>
 *
 *
 *
 * @author Mark Reinhold
 * @author JSR-51 Expert Group
 * @since 1.4
 */
public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> 

字段hb,offset,isReadOnly,2个构造函数


	// 这些字段是在这里声明的,而不是在Heap-X-Buffer中声明的,
	// 目的是减少访问这些值所需的虚方法调用的数量,在编写小型缓冲区时,这样做的代价特别高。
	final byte[] hb; // 非空仅用于堆缓冲区
	final int offset; // hb的偏移量
	boolean isReadOnly; // 仅对堆缓冲区有效

	// 使用给定的标记、位置、限制、容量、后备数组和数组偏移量创建一个新的缓冲区

	ByteBuffer(int mark, int pos, int lim, int cap, // package-private
			byte[] hb, int offset) {
		// 设置6个值
		super(mark, pos, lim, cap);
		this.hb = hb;
		this.offset = offset;
	}

	// 使用给定的标记、位置、限制和容量创建一个新的缓冲区
	// hb为null,offset为0
	ByteBuffer(int mark, int pos, int lim, int cap) { // package-private
		this(mark, pos, lim, cap, null, 0);
	}

方法allocateDirect,allocate,2个wrap,slice,duplicate,asReadOnlyBuffer


	/**
	 * 分配一个新的直接字节缓冲区。
	 *
	 * <p>
	 * 新缓冲区的位置将为零,它的限制将为它的容量,
	 * 它的标记将未定义,它的每个元素将初始化为零。
	 * 它是否有后备数组未指定。
	 *
	 * @param capacity The new buffer's capacity, in bytes
	 *
	 * @return The new byte buffer
	 *
	 * @throws IllegalArgumentException If the <tt>capacity</tt> is a negative
	 *                                  integer
	 */
	public static ByteBuffer allocateDirect(int capacity) {
		return new DirectByteBuffer(capacity);
	}

	/**
	 * 分配一个新的字节缓冲区。
	 *
	 * <p>
	 * 新缓冲区的位置将为零,它的限制将为它的容量,
	 * 它的标记将未定义,它的每个元素将初始化为零。
	 * 它将有一个后备数组,它的数组偏移量将为零。
	 *
	 * @param capacity The new buffer's capacity, in bytes
	 *
	 * @return The new byte buffer
	 *
	 * @throws IllegalArgumentException If the <tt>capacity</tt> is a negative
	 *                                  integer
	 */
	public static ByteBuffer allocate(int capacity) {
		if (capacity < 0)
			throw new IllegalArgumentException();
		return new HeapByteBuffer(capacity, capacity);
	}

	/**
	 * 将字节数组包装到缓冲区中。
	 *
	 * <p>
	 * 新的缓冲区将由给定的字节数组支持;
	 * 也就是说,对缓冲区的修改将导致数组被修改,反之亦然。
	 * 新的缓冲区的容量将是array.length,其位置为offset,其限制为offset + length,其标记将未定义。
	 * 它的后备数组将是给定的数组,它的数组偏移量将为零。
	 * </p>
	 *
	 * @param array  The array that will back the new buffer
	 *
	 * @param offset The offset of the subarray to be used; must be non-negative and
	 *               no larger than <tt>array.length</tt>. The new buffer's position
	 *               will be set to this value.
	 *
	 * @param len
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java NIO(New IO)是Java 1.4版本提供的一种新的IO API,它提供了与传统IO API不同的IO处理方式,包括了通道(channel)和缓冲区(buffer)的概念。Java NIO的目标是提供比传统IO更快、更高效的IO操作方式。 Java NIO源码解析需要深入了解Java NIO的核心概念,主要包括以下几个部分: 1. 缓冲区(Buffer):Java NIO中的缓冲区是一个对象,它包含了一定数量的数据元素,并且提供了对这些数据元素的基本操作方法。Java NIO中的所有数据都是通过缓冲区来传输的。 2. 通道(Channel):Java NIO中的通道是一种对象,它可以用来读取和写入数据。通道类似于流,但是它们可以被双向读写,并且可以同时处理多个线程。 3. 选择器(Selector):Java NIO中的选择器是一种对象,它可以用来监视多个通道的事件(如读写就绪),从而实现单线程处理多个通道的能力。 4. 文件处理:Java NIO中提供了一组文件处理的API,包括了文件读写、文件锁、文件映射等功能。 Java NIO源码解析需要深入研究Java NIO的实现细节,包括了缓冲区的实现、通道的实现、选择器的实现等。其中,缓冲区的实现是Java NIO的核心,也是最复杂的部分。Java NIO中的缓冲区是通过JNI(Java Native Interface)和Java堆内存来实现的,它提供了高效的数据传输方式,但是也带来了一些复杂性。通道的实现是基于底层的操作系统文件描述符来实现的,它提供了高效的IO操作方式,但是也需要考虑系统平台的差异性。选择器的实现是基于操作系统提供的事件驱动机制来实现的,它可以实现单线程同时处理多个通道的能力,但是也需要考虑系统平台的差异性。 总之,Java NIO源码解析需要深入理解Java NIO的核心概念和实现细节,这样才能更好地理解Java NIO的工作机制,并且能够在实际开发中灵活运用Java NIO的各种功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值