首页 > 编程知识 正文

java计算字符串长度,byte130输出结果

时间:2023-05-05 01:18:14 阅读:16534 作者:1984

1 .概念

Java NIO API中包含的缓冲类功能相当有限,并且未进行优化。 使用JDK处理ByteBuffer更加复杂。 因此,Netty的作者Trustin Lee重塑车轮以实现高效的网络传输,Netty的ByteBuf实质上相当于JDK的ByteBuffer,在Netty上通过Channel传输数据

2 .好处

可以定制缓冲区类型;

内置复合缓冲区类型,透明零拷贝(zero-copy );

flip )来切换读写模式) );

读取和写入索引分离;

方法链;

参照数;

游泳池。

3 .实现机制

ByteBuf实际上是对抽象字节数组byte[]的读写集合。 为了支持读写操作,有两个指针变量: readerIndex和writerIndex。 下图显示了如何使用两个指针将一个buffer分割为三个区域。

由此可知,ByteBuf真正读取的内容长度为writerIndex - readerIndex。

然后围绕读和写分析ByteBuf的实现逻辑。

3.1读取操作

读取操作主要具有以下功能:

获取readByte字节的内容;

获取readBoolean字节的内容,返回readByte!=0;

取readUnsignedByte字节的内容((short ) ) readByte )0xFF ) ); 可以将负数转换为无符号吗? )

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

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

获取读中间字节的内容,返回转换后的int类型;

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

取readInt字节的内容;

取readUnsignedInt字节的内容,readInt ()0xFFFFFFFFL;

读取长字节的内容;

获取readChar字节的内容;

取读浮动字节的int内容,转换为浮动类型;

取读双字节长内容,转换为双字节类型;

读取字节:获取指定长度的内容,返回字节总线类型;

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

读取字节:在目标容器中获取指定长度的内容。

3.2刻录

写入操作提供的功能主要是向字节缓冲区写入字节的内容,省略说明。 主要区别是在写入之前根据类型将其转换为相应长度的字节数组。

主要函数包括:写布尔、写字节、写短整型、写中间、写入长整型、写长整型、写微信、写浮动、写双精度、写双精度

3.3边界值安全

无论读写,字节buf数据都可能为空或已满,作为数据容器存在边界值检查,必须确保读写安全。

可读性检查

首先调用ensureAccessible ()方法以检查是否引用了ByteBuf对象。 如果引用计数器为0,指示对象将被释放并禁用,则抛出IllegalReferenceCountException异常,以确保以下操作不可用:

然后对读取参数进行合法性检查,不正当时抛出响应异常。

实现代码的框架如下:

protectedfinalvoidcheckreadablebytes (intminimumreadablebytes ) {

ensureAccessible (; if(minimumreadablebytes0(//参数为负,抛出参数错误异常

thrownewillegalargumentexception (;

} readerindexwriterindex-minimumreadablebytes (if )//容器中的可读字节不够,抛出越界异常

thrownewindexoutofboundsexception (;

}

}

可写检查

进行等待写入长度的合法性检查,如果没有合法性,这将抛出适当的异常。 如果小于可写长度,则返回正常。 否则,进行容量扩展,确保容量是2的指数幂。

实现代码框架如下:

publicbytebufensurewritable (intminwritablebytes ) if ) minwritable

Bytes < 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的类结构图如下所示:

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的派生类如下所示:

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

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的派生类如下所示:

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

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对象。

其派生类如下图所示:

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)

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。