java中byte的用法_nt宫颈长度多少是正常

java中byte的用法_nt宫颈长度多少是正常1.概念JavaNIOAPI自带的缓冲区类功能相当有限,没有经过优化,使用JDK的ByteBuffer操作更复杂。故而Netty的作者TrustinLee为了实现高效率的网络传输,重新造轮子,Netty中的ByteBuf实际上就相当于JDK中的ByteBuffer,其作用是在Netty中通过Channel传输数据。2.优势可以自定义缓冲类型;通过内置的复合缓冲类型,实现透明的零拷贝(ze…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1. 概念

Java NIO API自带的缓冲区类功能相当有限,没有经过优化,使用JDK的ByteBuffer操作更复杂。故而Netty的作者Trustin Lee为了实现高效率的网络传输,重新造轮子,Netty中的ByteBuf实际上就相当于JDK中的ByteBuffer,其作用是在Netty中通过Channel传输数据。

2. 优势

可以自定义缓冲类型;

通过内置的复合缓冲类型,实现透明的零拷贝(zero-copy);

不需要调用flip()来切换读/写模式;

读取和写入索引分开;

方法链;

引用计数;

Pooling(池)。

3. 实现机制

ByteBuf实际上是在一个抽象的字节数组byte[]上进行读/写操作的集合。它提供了两个指针变量用来支持读写操作:readerIndex和writerIndex。下图展现了如何将一个buffer利用两个指针来划分为三个区域。

bytebufStruct.jpg

由此可见,ByteBuf真正可读取的内容长度是writerIndex – readerIndex。

围绕着读和写操作,接下来分析ByteBuf的实现逻辑。

3.1 读操作

读操作主要提供以下功能:

readByte:取1字节的内容;

readBoolean:取1字节的内容,返回readByte()!= 0;

readUnsignedByte:取1字节的内容,返回((short) (readByte() & 0xFF));(能把负数转换为无符号吗?)

readShort:取2字节的内容,返回转换后的short类型;

readUnsignedShort:取2字节的内容,返回readShort()& 0xFFFF;

readMedium:取3字节的内容,返回转换后的int类型;

readUnsignedMedium:取3字节的内容,返回转换后的int类型;

readInt:取4字节的内容;

readUnsignedInt:取4字节的内容,返回readInt()& 0xFFFFFFFFL;

readLong:取8字节的内容;

readChar:取1字节的内容;

readFloat:取4字节的int内容,转换为float类型;

readDouble:取8字节的long内容,转换为double类型;

readBytes:取指定长度的内容,返回ByteBuf类型;

readSlice:取指定长度的内容,返回ByteBuf类型;

readBytes:取指定长度的内容到目标容器。

3.2 写操作

写操作提供的功能主要是往ByteBuf中写入byte内容,不再一一赘述。主要区别在于写入前根据类型转换为相对应长度的byte数组。

主要函数是:writeBoolean、writeByte、writeShort、writeMedium、writeInt、writeLong、writeChar、writeFloat、writeDouble、writeBytes、writeZero。

3.3 边界值安全

不论读或写,肯定会存在ByteBuf数据为空或满的情形,作为数据容器,要存在边界值检查,确保读写安全。

可读检查

首先调用ensureAccessible()方法来检查ByteBuf对象是否被引用,如果其引用计数器为0,代表该对象将要被释放,已失效,那么抛出IllegalReferenceCountException异常,确保不能够执行接下来的操作;

然后进行读取参数合法性检查,如不合法,则抛出响应的异常。

实现代码框架如下:

protected final void checkReadableBytes(intminimumReadableBytes) {

ensureAccessible();if (minimumReadableBytes < 0) {//参数为负,抛出参数非法异常

throw newIllegalArgumentException();

}if (readerIndex > writerIndex -minimumReadableBytes) {//容器中可读字节不够,抛出越界异常

throw newIndexOutOfBoundsException();

}

}

可写检查

进行待写入长度的合法性检查,如不合法,这抛出相应的异常。如果待写入小于可写的长度,则正常返回然;否则,进行容量的扩展,并确保容量是2的指数幂。

实现代码框架如下:

public ByteBuf ensureWritable(intminWritableBytes) {if (minWritableBytes < 0) {throw newIllegalArgumentException();

}if (minWritableBytes <=writableBytes()) {return this;

}if (minWritableBytes > maxCapacity -writerIndex) {throw newIndexOutOfBoundsException();

}//扩展现在的容量大小直到2的指数幂大小

int newCapacity = calculateNewCapacity(writerIndex +minWritableBytes);//调整容器到新的容量大小

capacity(newCapacity);return this;

}

在函数calculateNewCapacity()中,主要判断参数minNewCapacity与阈值threshold(4M)关系:

相等,则返回threshold;

大于,则按阈值(4MB)递增,返回增加后新容量newCapacity;

小于,newCapacity的初始大小设置为64字节,每次翻倍,直到newCapacity大于minNewCapacity为止,返回Math.min(newCapacity, maxCapacity)。

注:maxCapacity是使用者自己设定的ByteBuf容量上限。

4. 继承层次

ByteBuf的类结构图如下所示:

ByteBuf.jpg

4.1 AbstractByteBuf

实现ByteBuf的一个骨架,提供容器的上层操作实现,具体的读写内容需要依赖于具体的ByteBuf实现类。

AbstractByteBuf有两个实现类:AbstractDerivedByteBuf和AbstractReferenceCountedByteBuf。

4.1.1 AbstractDerivedByteBuf

ByteBuf的抽象基类,实现了包装另一个ByteBuf功能。在AbstractByteBuf的基础上提供了一下功能:

refCnt:获得该对象的引用计数;

retain:增加该对象的引用计数(无参数:+1;有参数:+指定的increment);

release:减少该对象的引用计数(无参数:-1;有参数:-指定的increment),当引用计数减少到0时,释放该对象。返回值为true,当且仅当引用计数变为0和该对象已释放。

internalNioBuffer:内部实现就是简单的调用nioBuffer(index, length);

nioBuffer:得到内部buffer的一个区域包装,即得到buffer的子区域作为NIO ByteBuffer,返回的ByteBuffer内容不会再受到原buffer索引或内容改变的影响。

AbstractDerivedByteBuf的派生类如下所示:

AbstractDerivedByteBuf.jpg

下面逐个分析下派生类的具体功能实现:

DuplicatedByteBuf

派生类buffer,简单的把所有的数据访问请求发送给内部的buffer。推荐使用ByteBuf.duplicate()来创建该对象,而不是直接调用本身的构造函数。

对象与内部的buffer共享该buffer整个区域的缓冲数据,只不过它们饿单独保持自己的索引标记。

ReadOnlyByteBuf

派生类buffer,将原有的ByteBuf包装为制度的ByteBuf,所有的写请求都将被禁止。推荐使用Unpooled.unmodifiableBuffer(ByteBuf)来创建该对象,而不是直接调用本身的构造函数。

对象与内部的buffer使用相同的索引标记,即共享readerIndex和writerIndex。

SlicedByteBuf

派生类buffer,仅暴露内部buffer的一个子区域,即切片。推荐使用ByteBuf.slice()或ByteBuf.slice(int, int)来创建该对象,而不是直接调用本身的构造函数。

4.1.2 AbstractReferenceCountedByteBuf

ByteBuf的抽象基类,实现了引用计数功能。

提供一个volatile类型的整型变量refCnt来记录引用次数。

主要的功能函数是refCnt、retain、release,用来更新引用次数refCnt。

AbstractReferenceCountedByteBuf的派生类如下所示:

AbstractReferenceCountedByteBuf.jpg

下面逐个分析下派生类的具体功能实现:

CompositeByteBuf

它是一个虚拟的buffer,将多个buffer合并为一个buffer,默认最大可以合并的buffer个数为DEFAULT_MAX_COMPONENTS = 16。推荐使用ByteBufAllocator.compositeBuffer()或Unpooled.wrappedBuffer(ByteBuf…),而不是直接调用本身的构造函数。

(合并操作还需仔细阅读源码,待完成)

FixedCompositeByteBuf

功能和CompositeByteBuf相似,只是以只读的方式合并一个ByteBuf数组。

在功能实现中,对于所有的可能更改buffers数组的set操作,均抛出ReadOnlyBufferException异常。

PooledByteBuf

Pooled的基类, 提供Pool的基本实现。

PooledByteBuf有三个衍生类:

PooledDirectByteBuf:提供池化的直接内存支持,基于 NIO ByteBuffer;

PooledHeapByteBuf:提供池化的堆内存支持, 基于byte[];

PooledUnsafeDirectByteBuf:提供池化的直接内存支持, 基于 NIO ByteBuffer。读写数据依赖于PlatformDependent,为了得到最佳性能,通过final类Unsafe来进行数据的读写。

ReadOnlyByteBufferBuf

包装一个只读的ByteBuffer,所有的set方法均抛出ReadOnlyBufferException异常。

它具有一个衍生类ReadOnlyUnsafeDirectByteBuf:

在ReadOnlyByteBufferBuf的基础上提供对direct ByteBuffer的支持,为了得到最佳性能,通过final类Unsafe来进行数据的读写。

UnpooledDirectByteBuf

提供非池化的直接内存支持, 基于 NIO ByteBuffer。推荐使用Unpooled.directBuffer(int)和Unpooled.wrappedBuffer(ByteBuffer)来替代本身的构造函数来生成对象。

它具有一个衍生类ThreadLocalPooledByteBuf。

UnpooledHeapByteBuf

提供非池化的堆内存支持, 基于byte[]。采用大端序来存储数据。

UnpooledUnsafeDirectByteBuf

提供非池化的直接内存支持,基于 NIO ByteBuffer。读写数据依赖于PlatformDependent,为了得到最佳性能,通过final类Unsafe来进行数据的读写。推荐使用Unpooled.directBuffer(int)和Unpooled.wrappedBuffer(ByteBuffer)来替代本身的构造函数来生成对象。

4.2 EmptyByteBuf

ByteBuf的直接实现类,构建一个容量和最大容量均为0的空ByteBuf。

它不能容纳数据,对于所有的get、set、read和write操作均抛出IndexOutOfBoundsException异常。

4.3 ReplayingDecoderBuffer

ByteBuf的直接实现类,buffer的数据读取采用ReplayingDecoder机制,它的原理是阻塞IO,当没有读取到足够的数据时,会抛出REPLY异常,然后进入循环while (in.isReadable())不断检查是否有足够的数据,直到读取到足够的数据放入到ReplayingDecoderBuffer对象中。

4.4 SwappedByteBuf

转换字节序的ByteBuf包装类,主要功能是交换内部ByteBuf的字节序列,即大端序BIG_ENDIAN和小端序LITTLE_ENDIAN之间的转换。

4.5 WrappedByteBuf

ByteBuf的包装类,将所有方法调用委派给被包装的ByteBuf对象。

其派生类如下图所示:

WrappedByteBuf.jpg

4.5.1 AdvancedLeakAwareByteBuf

为了方便监控ByteBuf的泄露,AdvancedLeakAwareByteBuf的所有方法都添加了leak.record(),用来记录调用者当前栈的踪迹,从而ResourceLeakDetector就可以发现最后被访问的泄漏资源是哪个。

4.5.2 SimpleLeakAwareByteBuf

实现方式和AdvancedLeakAwareByteBuf非常相似,但只对order方法添加了资源泄露的检查动作leak.record()。

4.5.3 UnreleasableByteBuf

包装其它的buffer到一个ByteBuf,用于阻止用户增加或减少这个包装buffer的引用计数,防止他人对ByteBuf的销毁动作。

一般的使用场景就是定义特殊的常量ByteBuf,然后包装成unreleasableBuffer()后就不怕被其他人错误的销毁掉:

public abstract class HttpObjectEncoder extends MessageToMessageEncoder{private static final ByteBuf CRLF_BUF =unreleasableBuffer(directBuffer(CRLF.length).writeBytes(CRLF));

}

(END)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/191647.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 基于经纬度做航线图可视化的软件_碧蓝航线是哪家公司做的

    基于经纬度做航线图可视化的软件_碧蓝航线是哪家公司做的基于经纬度画航线图介绍代码介绍这阵子在处理航空公司的数据,为了PPT展示好看,做了几个可视化图。这里用的是pyecharts第三方库。pyecharts库的相关介绍,可以上设计文档看看相关说明。https://pyecharts.org/#/zh-cn/series_options代码importpandasaspddata=pd.read_csv(“airline_info.csv”,encoding=’gbk’)print(data)#数据太多,画出来太密了,这里选了

  • HTTP协议

    当你在浏览器地址栏敲入“http://www.cnblogs.com/”,然后猛按回车,呈现在你面前的,将是博客园的首页了(这真是废话,你会认为这是理所当然的)。作为一个开发者,尤其是web开发人员,

  • 如何用串口助手测试软件485通讯功能,串口调试助手如何检测RS485端口好坏及信号发送的好坏?…

    如何用串口助手测试软件485通讯功能,串口调试助手如何检测RS485端口好坏及信号发送的好坏?…串口是用来通信的,如果能正常通信,串口当然就是好的!所以,最可靠的方法就是建立一个串口通信环境。当然,也有简单的方法,那就是短接串口的2、3两针,这样就形成一个自发自收的环境,再用串口调试助手发送数据,如果有数据回显,大致说明串口通信功能正常!当然,标准串口信号很多,最可靠的方法还是建立一个串口通信环境。拓展:1、串口调试助手是串口调试相关工具,有多个版本。如:友善串口调试助手,支持960…

  • zookeeper下载及安装教程_Zookeeper未授权访问漏洞

    zookeeper下载及安装教程_Zookeeper未授权访问漏洞学习黑马传智健康项目过程中,zookeeper的下载与安装

    2022年10月24日
  • Silverlight群建立了,欢迎加入SilverlightQQ群!

    Silverlight群建立了,欢迎加入SilverlightQQ群!Silverlight群建立了,欢迎加入SilverlightQQ群,一切关于WPF(Windows Presentation Foundation)&Silverlight(RIA程序开发),欢迎大家上传Silverlight共享文档 加群者:”Silverlight爱好者或WPF爱好者”即可,拒绝潜水份子…群号:50992947论坛上的http://topic.csdn.n

  • Symantec 卸载密码方法

    Symantec 卸载密码方法Symantec卸载密码方法最的有很多朋友问…方法一:当时就是输入在服务器端设置的密码(诺顿的默认密码是symantec)方法二:修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\INTEL\LANDesk\VirusProtect6CurrentVersion\AdministratorOnly\Security修改UseV…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号