摘要:提供了作為它的字節(jié)容器但是這個(gè)類使用起來過于復(fù)雜而且也有些繁瑣的的代替品是的的數(shù)據(jù)處理通過兩個(gè)組件暴露下面是的優(yōu)點(diǎn)它可以被用戶自定義的緩沖區(qū)類擴(kuò)展通過內(nèi)置的復(fù)合緩沖區(qū)類型實(shí)現(xiàn)了透明的零拷貝容量可以按需增長在讀和寫這兩種模式之間雀環(huán)不需要調(diào)用
Java NIO 提供了 ByteBuffer 作為它的字節(jié)容器, 但是這個(gè)類使用起來過于復(fù)雜, 而且也有些繁瑣.
Netty 的 ByteBuffer 的代替品是 ByteBuf.
ByteBuf 的 API
Netty 的數(shù)據(jù)處理 API 通過兩個(gè)組件暴露
public abstract class ByteBuf implements ReferenceCounted, Comparablepublic interface ByteBufHolder extends ReferenceCounted
下面是 ByteBuf API 的優(yōu)點(diǎn):
它可以被用戶自定義的緩沖區(qū)類擴(kuò)展;
通過內(nèi)置的復(fù)合緩沖區(qū)類型實(shí)現(xiàn)了透明的零拷貝;
容量可以按需增長;
在讀和寫這兩種模式之間雀環(huán)不需要調(diào)用 ByteBuffer 的 flip() 方法;
讀和寫試用了不同的索引;
支持方法的鏈?zhǔn)秸{(diào)用;
支持引用計(jì)數(shù);
支持池化.
它是如何工作的ByteBuf 維護(hù)了兩個(gè)不同的索引: 一個(gè)用于讀取, 一個(gè)用于寫入. 當(dāng)你從 ByteBuf 讀取時(shí), 它的 readerIndex 將會(huì)被遞增到讀取的字節(jié)數(shù). 同樣的, 當(dāng)你寫入 ByteBuf 時(shí), 它的 writerIndex 也會(huì)被遞增.
要了解這些索引兩兩之間的關(guān)系, 請(qǐng)考慮一下, 如果打算讀取字節(jié)直到 readerIndex 達(dá)到和 writerIndex 同樣的值時(shí)會(huì)發(fā)生什么.
在那時(shí), 你將會(huì)到達(dá) "可以讀取的" 數(shù)據(jù)的末尾. 就如同試圖讀取超出數(shù)組末尾的數(shù)據(jù)一樣, 會(huì)觸發(fā)一個(gè) IndexOutOfBoundsException.
名稱以 read 或 write 開頭的 ByteBuf 方法, 將會(huì)推進(jìn)其對(duì)應(yīng)的索引, 而名稱以 set 或 get 開頭的操作則不會(huì). 后面的這些方法將在作為一個(gè)參數(shù)傳入的一個(gè)相對(duì)索引上執(zhí)行操作.
可以指定 ByteBuf 的最大容量. 默認(rèn)的限制是 Interger.MAX_VALUE.ByteBuf 的使用模式 堆緩沖區(qū)
最常用的 ByteBuf 模式是將數(shù)據(jù)存儲(chǔ)在 JVM 的堆空間中. 這種模式被稱為 支撐數(shù)組 , 它能在沒有使用池化的情況下提供快速的分配和釋放. 代碼如下:
public static void main(String args[]) { ByteBuf heapBuf = Unpooled.copiedBuffer("heap space", CharsetUtil.UTF_8); if (heapBuf.hasArray()) { // 檢查 ByteBuf 是否有一個(gè)支持?jǐn)?shù)組 byte[] array = heapBuf.array(); int offset = heapBuf.arrayOffset() + heapBuf.readerIndex();// 計(jì)算第一個(gè)字節(jié)的偏移量 int length = heapBuf.readableBytes();// 計(jì)算可讀字節(jié)數(shù) System.out.println(Arrays.toString(array)); System.out.println(offset); System.out.println(length); } else { System.out.println("No Heap Array"); } }
當(dāng) hasArray() 返回 false 時(shí)嘗試訪問支持?jǐn)?shù)組會(huì)拋出 UnsupportedOperationException. 這個(gè)用法與JDK的 ByteBuffer 類似.直接緩沖區(qū)
直接緩沖區(qū)是另外一種 ByteBuf 模式.
直接緩沖區(qū)的內(nèi)容并不是駐留在 Java 的堆上, 利用 java.nio.ByteBuffer 是借助于 JVM 調(diào)用操作系統(tǒng)的底層通信函數(shù), 直接操作直接緩沖區(qū)可以減少中間緩沖區(qū)的復(fù)制操作, 進(jìn)而提供程序性能, 其目的是:
通過免去中間交換的內(nèi)存拷貝(從程序內(nèi)存拷貝到系統(tǒng)內(nèi)存), 提升IO處理速度; 直接緩沖區(qū)的內(nèi)容可以駐留在垃圾回收掃描的堆區(qū)以外.
DirectBuffer 在 -XX:MaxDirectMemorySize=xxM 大小限制下, 使用 Heap 之外的內(nèi)存, GC對(duì)此 ”無能為力” , 也就意味著規(guī)避了在高負(fù)載下頻繁的 GC 過程對(duì)應(yīng)用線程的中斷影響.
但是直接緩沖區(qū)的缺點(diǎn)是在內(nèi)存空間的分配和釋放上比堆緩沖區(qū)更復(fù)雜, 另外一個(gè)缺點(diǎn)是如果要將數(shù)據(jù)傳遞給遺留代碼處理, 因?yàn)閿?shù)據(jù)不是在堆上, 你可能不得不作出一個(gè)副本, 如下:
public static void main(String args[]) { ByteBuf directBuf = Unpooled.directBuffer(100); directBuf.writeBytes("direct buffer".getBytes()); if (!directBuf.hasArray()) { // 檢查 ByteBuf 是否由數(shù)組支撐. 如果不是, 則這是一個(gè)直接緩沖區(qū) int length = directBuf.readableBytes(); // 獲取可讀字節(jié)數(shù) byte[] array = new byte[length]; // 分配一個(gè)新的數(shù)組來保存具有該長度的字節(jié)數(shù)據(jù) directBuf.getBytes(directBuf.readerIndex(), array); // 將字節(jié)復(fù)制到該數(shù)組 System.out.println(Arrays.toString(array)); System.out.println(length); } }復(fù)合緩沖區(qū)
復(fù)合緩沖區(qū)為多個(gè) ByteBuf 提供一個(gè)聚合視圖, 可以根據(jù)需要添加或者刪除 ByteBuf 實(shí)例.
Netty 提供了 ByteBuf 的子類 CompositeByteBuf 類來處理復(fù)合緩沖區(qū), CompositeByteBuf 只是一個(gè)視圖.
CompositeByteBuf 中的 ByteBuf 實(shí)例可能同時(shí)包含直接內(nèi)存分配和非直接內(nèi)存分配.
如果其中只有一個(gè)實(shí)例, 那么對(duì) CompositeByteBuf 上的 hasArray() 方法的調(diào)用將返回該組件上的 hasArray()方法的值; 否則它將返回 false. 因?yàn)橛锌赡馨苯泳彌_區(qū)或堆緩沖區(qū).
例如, 一條消息由 header 和 body 兩部分組成, 將 header 和 body 組裝成一條消息發(fā)送出去, 可能 body 相同, 只是 header 不同, 使用 CompositeByteBuf 就不用每次都重新分配一個(gè)新的緩沖區(qū).
下圖顯示CompositeByteBuf 組成 header 和 body:
下面代碼顯示了使用 JDK 的 ByteBuffer 的一個(gè)實(shí)現(xiàn). 兩個(gè) ByteBuffer 的數(shù)組創(chuàng)建保存消息的組件,第三個(gè)創(chuàng)建用于保存所有數(shù)據(jù)的副本.
// 使用數(shù)組保存消息的各個(gè)部分 ByteBuffer[] message = { header, body }; // 使用副本來合并這兩個(gè)部分 ByteBuffer message2 = ByteBuffer.allocate( header.remaining() + body.remaining()); message2.put(header); message2.put(body); message2.flip();
這種做法顯然是低效的; 分配和復(fù)制操作不是最優(yōu)的方法, 操縱數(shù)組使代碼顯得很笨拙.
下面看使用 CompositeByteBuf 的改進(jìn)版本.
/** * Netty 通過一個(gè) ByteBuf 子類——CompositeByteBuf——實(shí)現(xiàn)了組合模式,它提供了一 個(gè)將多個(gè)緩沖區(qū)表示為單個(gè)合并緩沖區(qū)的虛擬表示 */ public class CompositeBuf { public static void main(String args[]){ CompositeByteBuf messageBuf = Unpooled.compositeBuffer(); ByteBuf headerBuf = Unpooled.copiedBuffer("head", CharsetUtil.UTF_8); // can be backing or direct ByteBuf bodyBuf = Unpooled.copiedBuffer("body", CharsetUtil.UTF_8); // can be backing or direct messageBuf.addComponents(headerBuf, bodyBuf); System.out.println("Remove Head Before------------------"); printCompositeBuffer(messageBuf); for (ByteBuf buf : messageBuf) { System.out.println(buf.toString(CharsetUtil.UTF_8)); } messageBuf.removeComponent(0); // remove the header System.out.println("Remove Head After------------------"); printCompositeBuffer(messageBuf); for (ByteBuf buf : messageBuf) { System.out.println(buf.toString(CharsetUtil.UTF_8)); } } public static void printCompositeBuffer(CompositeByteBuf compBuf){ int length = compBuf.readableBytes(); byte[] array = new byte[length]; compBuf.getBytes(compBuf.readerIndex(), array); System.out.println (Arrays.toString(array)); System.out.println (length); } }
Netty 嘗試使用 CompositeByteBuf 優(yōu)化 socket I/O 操作, 消除原生 JDK 中可能存在的的性能低和內(nèi)存消耗問題.
雖然這是在 Netty 的核心代碼中進(jìn)行的優(yōu)化, 并且是不對(duì)外暴露的, 但是作為開發(fā)者還是應(yīng)該意識(shí)到其影響.
ByteBuf分配從空間初始化方式上來分, ByteBuf 分為: 緩存方式分配和非緩存方式分配.
5.1 使用 ByteBufAllocator 接口分配為了降低分配和釋放內(nèi)存的開銷, Netty 通過 interface ByteBufAllocator 實(shí)現(xiàn)了 ByteBuf 的池化, 它可以用來分配我們所描述過的任意類型的 ByteBuf 實(shí)例 (基于堆緩沖區(qū)的, 基于直接緩沖區(qū)的, 基于復(fù)合緩沖區(qū)的).
// 返回一個(gè)基于堆或者直接內(nèi)存存儲(chǔ)的 ByteBuf ByteBuf buffer(); ByteBuf buffer(int initialCapacity); ByteBuf buffer(int initialCapacity, int maxCapacity); // 返回一個(gè)基于堆內(nèi)存的 ByteBuf ByteBuf heapBuffer(); ByteBuf heapBuffer(int initialCapacity); ByteBuf heapBuffer(int initialCapacity, int maxCapacity); // 返回一個(gè)基于直接內(nèi)存的 ByteBuf ByteBuf directBuffer(); ByteBuf directBuffer(int initialCapacity); ByteBuf directBuffer(int initialCapacity, int maxCapacity); // 通過設(shè)置一個(gè)最大值, 基于堆內(nèi)存或直接內(nèi)存, 返回一個(gè)混合緩沖區(qū). CompositeByteBuf compositeBuffer(int maxNumComponents); CompositeByteBuf compositeHeapBuffer(); CompositeByteBuf compositeHeapBuffer(int maxNumComponents); CompositeByteBuf compositeDirectBuffer(); CompositeByteBuf compositeDirectBuffer(int maxNumComponents); // 返回一個(gè)用于套接字 I/O 操作的 ByteBuf ioBuffer()
ioBuffer() 重點(diǎn)
默認(rèn)的, 當(dāng)所運(yùn)行的環(huán)境具有 sun.misc.Unsafe 支持時(shí), 返回基于直接內(nèi)存的 ByteBuf, 否則返回一個(gè)基于堆內(nèi)存的 ByteBuf; 當(dāng)指定使用 PreferHeapByteBufAllocator 時(shí), 則只會(huì)返回基于堆內(nèi)存的 ByteBuf.
可以通過 Channle(每個(gè)都可以有一個(gè)不同的 ByteBufAllocator 實(shí)例) 或者 ChannleHandlerContext 獲取到 ByteBufAllocator.
Netty 提供了兩種 ByteBufAllocator 的實(shí)現(xiàn):
Channel channel = ...; ByteBufAllocator byteBufAllocator = channel.alloc(); ChannelHandlerContext channelHandlerContext = ...; ByteBufAllocator bufAllocator = channelHandlerContext.alloc();
前者池化了ByteBuf 的實(shí)例以提高性能并最大限度地減少內(nèi)存碎片(PooledByteBufAllocator 默認(rèn)).
后者不池化ByteBuf實(shí)例, 并且在每次它被調(diào)用時(shí)都會(huì)返回一個(gè)新的實(shí)例(UnpooledByteBufAllocator).
可能某些情況下, 你未能獲取一個(gè)到 ByteBufAllocator 的引用. 對(duì)于這種情況, Netty 提供了一個(gè)簡單的稱為 Unpooled(封裝了 UnpooledByteBufAllocator) 的工具類, 它提供了靜態(tài)的輔助方法來創(chuàng)建未池化的 ByteBuf 實(shí)例. 提供的方法如下:
buffer: 返回一個(gè)未池化的基于堆內(nèi)存存儲(chǔ)的 ByteBuf.
directBuffer: 返回一個(gè)未池化的基于直接內(nèi)存存儲(chǔ)的 ByteBuf
wrappedBuffer: 返回一個(gè)包裝了給定數(shù)據(jù)的 ByteBuf
copiedBuffer: 返回一個(gè)復(fù)制了給定數(shù)據(jù)的 ByteBuf
ByteBuf directBuf = Unpooled.directBuffer(100); directBuf.writeBytes("direct buffer".getBytes()); System.out.println(directBuf.indexOf(0,directBuf.readableBytes(), (byte) "u"));
Unpooled 類還使得 ByteBuf 同樣可用于那些并不需要 Netty 的其他組件的非網(wǎng)絡(luò)項(xiàng)目, 使得其能得益于高性能的可擴(kuò)展的緩沖區(qū) API.隨機(jī)訪問索引
如同在普通的 Java 字節(jié)數(shù)組中一樣, ByteBuf 的索引是從零開始的: 第一個(gè)字節(jié)的索引是0, 最后一個(gè)字節(jié)的索引總是 capacity() - 1, 可以通過 index 進(jìn)行訪問:
public static void main(String args[]) { ByteBuf directBuf = Unpooled.directBuffer(100); directBuf.writeBytes("direct buffer".getBytes()); System.out.println(directBuf.getByte(5)); }
這種方式并不會(huì)改變 readerIndex 和 weiterIndex. 如果有需要, 也可以通過調(diào)用 readerIndex(index) 或者 writerIndex(index) 來手動(dòng)移動(dòng)這兩者.順序訪問索引
雖然 ByteBuf 同時(shí)具有讀索引和寫索引, 但是 JDK 的 ByteBuffer 卻只有一個(gè)索引, 這也就是為什么必須調(diào)用 flip() 方法來在讀模式和寫模式之間進(jìn)行切換的原因. ByteBuf 被兩個(gè)索引劃分成 3 個(gè)區(qū)域.
可丟棄的字節(jié)可丟棄字節(jié)的分段包含了已經(jīng)被讀過的字節(jié). 通過調(diào)用 discardReadBytes() 方法, 可以丟棄它們并回收空間. 這個(gè)分段的初始大小為 0, 存儲(chǔ)在 readerIndex 中, 會(huì)隨著 read 操作的執(zhí)行而增加.
下圖展示的緩沖區(qū)上調(diào)用 discardReadBytes() 方法后的結(jié)果. 可以看到, 可丟棄字節(jié)分段中的空間已經(jīng)變?yōu)榭蓪懙牧?
注意, 在調(diào)用 discardReadBytes() 之后, 對(duì)可寫分段的內(nèi)容并沒有任何的保證.
頻繁地調(diào)用 discardReadBytes() 方法可以確保可寫分段的最大化, 但是這將極有可能會(huì)導(dǎo)致內(nèi)存復(fù)制, 因?yàn)榭勺x字節(jié) (圖中標(biāo)記為 CONTENT 的部分) 必須被移動(dòng)到緩沖區(qū)的開始位置. 我們建議只在有真正需要的時(shí)候才這樣做, 例如, 當(dāng)內(nèi)存非常寶貴的時(shí)候.
可讀字節(jié)ByteBuf 的可讀字節(jié)分段存儲(chǔ)了實(shí)際數(shù)據(jù). 新分配的、包裝的或者復(fù)制的緩沖區(qū)默認(rèn) readerIndex 值為 0. 任何名稱以 read 或者 skip 開頭的操作都將檢索或者跳過位于當(dāng)前 readerIndex 的數(shù)據(jù), 并且將它增加已讀字節(jié)數(shù).
如果嘗試在緩沖區(qū)的可讀字節(jié)數(shù)已經(jīng)耗盡時(shí)從中讀取數(shù)據(jù), 那么將會(huì)引發(fā)一個(gè) IndexOutOfBoundsException.
可寫字節(jié)可寫字節(jié)分段是指一個(gè)擁有未定義內(nèi)容的、寫入就緒的內(nèi)存區(qū)域. 新分配的緩沖區(qū)的 writerIndex 的默認(rèn)值為 0. 任何名稱以 write 開頭的操作都將從當(dāng)前的 writerIndex 處開始寫數(shù)據(jù), 并將它增加已經(jīng)寫入的字節(jié)數(shù).
如果寫操作的目標(biāo)也是 ByteBuf, 并且沒有指定源索引的值, 則源緩沖區(qū)的 readerIndex 也同樣會(huì)被增加相同的大小.
如果嘗試往目標(biāo)寫入超過目標(biāo)容量的數(shù)據(jù), 將會(huì)引發(fā)一個(gè) IndexOutOfBoundException.
例子ByteBuf directBuf = Unpooled.directBuffer(100); directBuf.writeBytes("direct buffer".getBytes()); System.out.println("可寫字節(jié)容量:"+directBuf.writableBytes()); System.out.println("初始化可讀字節(jié):"+directBuf.readableBytes()); System.out.println("初始化可丟棄字節(jié):"+directBuf.readerIndex()+" "); directBuf.readBytes(2); System.out.println("讀取兩個(gè)字節(jié)"+" "); System.out.println("讀取后可寫字節(jié)容量:"+directBuf.writableBytes()); System.out.println("讀取后可讀字節(jié):"+directBuf.readableBytes()); System.out.println("讀取后可丟棄字節(jié):"+directBuf.readerIndex()+" "); directBuf.discardReadBytes(); System.out.println("執(zhí)行discardReadBytes后可寫字節(jié)容量:"+directBuf.writableBytes()); System.out.println("執(zhí)行discardReadBytes后可讀字節(jié):"+directBuf.readableBytes()); System.out.println("執(zhí)行discardReadBytes后可丟棄字節(jié):"+directBuf.readerIndex());
輸出為:
可寫字節(jié)容量:87 初始化可讀字節(jié):13 初始化可丟棄字節(jié):0 讀取兩個(gè)字節(jié) 讀取后可寫字節(jié)容量:87 讀取后可讀字節(jié):11 讀取后可丟棄字節(jié):2 執(zhí)行discardReadBytes后可寫字節(jié)容量:89 執(zhí)行discardReadBytes后可讀字節(jié):11 執(zhí)行discardReadBytes后可丟棄字節(jié):0索引管理
索引管理的相關(guān)操作如下:
可以通過調(diào)用 markReaderIndex()、 markWriterIndex()、 resetWriterIndex() 和 resetReaderIndex() 來標(biāo)記和重置 ByteBuf 的 readerIndex 和 writerIndex.
可以通過調(diào)用 readerIndex(int) 或者 writerIndex(int) 來將索引移動(dòng)到指定位置. 試圖將任何一個(gè)索引設(shè)置到一個(gè)無效的位置都將導(dǎo)致一個(gè) IndexOutOfBoundsException.
可以通過調(diào)用 clear() 方法來將 readerIndex 和 writerIndex 都設(shè)置為 0. 調(diào)用 clear() 比調(diào)用 discardReadBytes() 輕量得多, 因?yàn)樗鼘⒅皇侵刂盟饕粫?huì)復(fù)制任何的內(nèi)存.
示例如下:
ByteBuf directBuf = Unpooled.directBuffer(100); directBuf.writeBytes("direct buffer".getBytes()); System.out.println("初始化可讀字節(jié):"+directBuf.readableBytes()); directBuf.markReaderIndex(); System.out.println("執(zhí)行markReaderIndex"+" ");//標(biāo)記讀索引 directBuf.readBytes(2); System.out.println("讀取兩個(gè)字節(jié)"+" "); System.out.println("讀取后可讀字節(jié):"+directBuf.readableBytes()); directBuf.resetReaderIndex();//恢復(fù)讀索引 System.out.println("執(zhí)行resetReaderIndex后可讀字節(jié):"+directBuf.readableBytes()); directBuf.clear(); System.out.println("執(zhí)行clear后可讀字節(jié):"+directBuf.readableBytes()); directBuf.readBytes(2);//可讀字節(jié)變?yōu)?,此時(shí)再讀取會(huì)拋出IndexOutOfBoundsException
輸出如下:
初始化可讀字節(jié):13 執(zhí)行markReaderIndex 讀取兩個(gè)字節(jié) 讀取后可讀字節(jié):11 執(zhí)行resetReaderIndex后可讀字節(jié):13 執(zhí)行clear后可讀字節(jié):0 Exception in thread "main" java.lang.IndexOutOfBoundsException: readerIndex(0) + length(2) exceeds writerIndex(0): UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(ridx: 0, widx: 0, cap: 100) at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1403) at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1390) at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:843) at com.eric.bytebuf.OperationSample.indexManage(OperationSample.java:32) at com.eric.bytebuf.OperationSample.main(OperationSample.java:16)派生緩沖區(qū)
派生緩沖區(qū)為 ByteBuf 提供了以專門的方式來呈現(xiàn)其內(nèi)容的視圖。這類視圖是通過以下方法被創(chuàng)建的:
duplicate() slice() slice(int, int) Unpooled.unmodifiableBuffer(…) order(ByteOrder) readSlice(int)
上述這些方法都將返回一個(gè)新的 ByteBuf 實(shí)例, 它具有自己的讀索引、寫索引和標(biāo)記 索引.
但是其內(nèi)部存儲(chǔ)和原始對(duì)象是共享的. 該種方式創(chuàng)建成本很低廉, 但是這也意味著, 如果你修改了它的內(nèi)容, 也同時(shí)修改了其對(duì)應(yīng)的源實(shí)例, 所以要小心.
如果需要一個(gè)現(xiàn)有緩沖區(qū)的真實(shí)副本, 請(qǐng)使用 copy() 或者 copy(int, int) 方法. 不同于派生緩沖區(qū), 由這個(gè)調(diào)用所返回的 ByteBuf 擁有獨(dú)立的數(shù)據(jù)副本.
Charset utf8 = Charset.forName("UTF-8"); ByteBuf buf = Unpooled.copiedBuffer("Netty in Action rocks!", utf8); ByteBuf slice = buf.slice(0, 15); System.out.println(slice.toString(utf8)); buf.setByte(0,"J"); assert buf.getByte(0) == slice.getByte(0);讀/寫操作
正如前文所提到過的, 有兩種類別的讀/寫操作:
get() 和 set() 操作, 從給定的索引開始,并且保持索引不變;
read() 和 write() 操作, 從給定的索引開始,并且會(huì)根據(jù)已經(jīng)訪問過的字節(jié)數(shù)對(duì)索引進(jìn)行調(diào)整.
ByteBufHolder我們經(jīng)常發(fā)現(xiàn), 除了實(shí)際的數(shù)據(jù)負(fù)載之外, 我們還需要存儲(chǔ)各種屬性值. HTTP 響應(yīng)便是一個(gè)很好的例子, 除了表示為字節(jié)的內(nèi)容, 還包括狀態(tài)碼、cookie 等.
為了處理這種常見的用例, Netty 提供了 ByteBufHolder. ByteBufHolder 也為 Netty 的高級(jí)特性提供了支持, 如緩沖區(qū)池化, 其中可以從池中借用 ByteBuf, 并且在需要時(shí)自動(dòng)釋放.
ByteBufHolder 只有幾種用于訪問底層數(shù)據(jù)和引用計(jì)數(shù)的方法:
content(): 返回由這個(gè) ByteBufHolder 所持有的 ByteBuf.
copy(): 返回這個(gè) ByteBufHolder 的一個(gè)深拷貝, 包括一個(gè)其所包含的 ByteBuf 的非共享拷貝.
duplicate(): 返回這個(gè) ByteBufHolder 的一個(gè)淺拷貝, 包括一個(gè)其所包含的 ByteBuf 的共享拷貝.
系統(tǒng)默認(rèn)自帶了一系列的 ByteBufHolder, 以 MemoryFileUpload 為例, 該類通過封裝將 filename, contentType, contentTransferEncoding 屬性與對(duì)應(yīng)的file進(jìn)行關(guān)聯(lián).
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/74269.html
摘要:轉(zhuǎn)發(fā)自 轉(zhuǎn)發(fā)自 http://netty.io/wiki/referenc... Since Netty version 4, the life cycle of certain objects are managed by their reference counts, so that Netty can return them (or their shared resources)...
摘要:根據(jù)對(duì)的定義即所謂的就是在操作數(shù)據(jù)時(shí)不需要將數(shù)據(jù)從一個(gè)內(nèi)存區(qū)域拷貝到另一個(gè)內(nèi)存區(qū)域因?yàn)樯倭艘淮蝺?nèi)存的拷貝因此的效率就得到的提升在層面上的通常指避免在用戶態(tài)與內(nèi)核態(tài)之間來回拷貝數(shù)據(jù)例如提供的系統(tǒng)調(diào)用它可以將一段用戶空間內(nèi)存映射到內(nèi) 根據(jù) Wiki 對(duì) Zero-copy 的定義: Zero-copy describes computer operations in which the C...
摘要:使用來優(yōu)化套接字操作,盡可能消除由的緩沖區(qū)實(shí)現(xiàn)所導(dǎo)致的性能以及內(nèi)存使用率的懲罰,這種優(yōu)化發(fā)生在的核心代碼中,不會(huì)被暴露出來。當(dāng)前將會(huì)被增加所寫入的字節(jié)數(shù)。 ByteBuf是Java NIO ByteBuffer的替代品,是網(wǎng)絡(luò)數(shù)據(jù)基本單位字節(jié)的容器。 ByteBuf的API Netty的數(shù)據(jù)處理API通過兩個(gè)組件暴漏:抽象類ByteBuf和接口ByteBufHolder ByteBuf...
摘要:當(dāng)你從讀取時(shí),它的將會(huì)被遞增已經(jīng)被讀取的字節(jié)數(shù)。達(dá)到和位于同一位置,表示我們到達(dá)可以讀取的數(shù)據(jù)的末尾。該應(yīng)用程序可以選擇為多個(gè)消息重用相同的消息主體。 ByteBuffer 當(dāng)我們進(jìn)行數(shù)據(jù)傳輸?shù)臅r(shí)候,往往需要使用到緩沖區(qū),常用的緩沖區(qū)就是JDK NIO類庫提供的java.nio.Buffer。 showImg(https://segmentfault.com/img/bVbbz8p?w...
摘要:主要用來檢測(cè)對(duì)象是否泄漏。子類實(shí)現(xiàn)相關(guān)的方法是否支持?jǐn)?shù)組,判斷緩沖區(qū)的實(shí)現(xiàn)是否基于字節(jié)數(shù)組如果緩沖區(qū)的實(shí)現(xiàn)基于字節(jié)數(shù)組,返回字節(jié)數(shù)組 ByteBuf ByteBuf需要提供JDK ByteBuffer的功能(包含且不限于),主要有以下幾類基本功能: 7種Java基礎(chǔ)類型、byte[]、ByteBuffer(ByteBuf)的等的讀寫 緩沖區(qū)自身的copy和slice 設(shè)置網(wǎng)絡(luò)字節(jié)序 ...
閱讀 2899·2021-10-27 14:19
閱讀 537·2021-10-18 13:29
閱讀 1128·2021-07-29 13:56
閱讀 3547·2019-08-30 13:19
閱讀 1926·2019-08-29 12:50
閱讀 1035·2019-08-23 18:16
閱讀 3521·2019-08-22 15:37
閱讀 1897·2019-08-22 15:37