Each type of bytebuf has a corresponding dispenser bytebufallocator, similar to the factory model. We will first learn unpooledheapbytebuf and its corresponding dispenser Unpooledbytebufallocator
How to know the alloc dispenser is that a?
Can be downloaded from the official Timeserver example to learn, the project has a source code can be traced in the Testchannelhandler.class breakpoint
From the figure can be seen Netty 4.1.8 default bytebufallocator is Pooledbytebufallocator, you can participate in the startup parameters-dio.netty.allocator.type unpooled/pooled settings
Careful readers can see that the allocation of bytebuf only pool and unpool, but there are many types of bytebuf, may be due to the use of considerations, sometimes not necessarily design too rigid, too standard, but it makes learning cost is very large
Public Final classBytebufutil {Static FinalBytebufallocator Default_allocator; Static{String Alloctype=Systempropertyutil.get ("Io.netty.allocator.type", platformdependent.isandroid ()? "unpooled": "Pooled"); Alloctype=alloctype.tolowercase (locale.us). Trim (); Bytebufallocator Alloc; if("unpooled". Equals (Alloctype)) {Alloc=Unpooledbytebufallocator.default; } Else if("Pooled". Equals (Alloctype)) {Alloc=Pooledbytebufallocator.default; } Else{alloc=Pooledbytebufallocator.default;} default_allocator=Alloc; }}
ABSTRACTREFERENCECOUNTEDBYTEBUF is the total number of statistical citations processed, using atomic* technology.
REFCNT is starting from 1, with each reference once plus 1, releasing the reference minus 1 when refcnt becomes 1 o'clock execution deallocate the subclass implementation
Public Abstract classAbstractreferencecountedbytebufextendsAbstractbytebuf {Private Static FinalAtomicintegerfieldupdater<abstractreferencecountedbytebuf> Refcntupdater =Atomicintegerfieldupdater.newupdater (abstractreferencecountedbytebuf.class, "refcnt"); Private volatile intrefcnt = 1; @Override PublicBytebuf retain () {returnRetain0 (1); } PrivateBytebuf Retain0 (intincrement) { for (;;) { intrefcnt = This. refcnt; Final intnextcnt = refcnt +increment; if(Nextcnt <=increment) { Throw Newillegalreferencecountexception (refcnt, increment); } if(Refcntupdater.compareandset ( This, refcnt, nextcnt)) { Break; } } return This; } @Override Public Booleanrelease () {returnRELEASE0 (1); } Private BooleanRELEASE0 (intdecrement) { for (;;) { intrefcnt = This. refcnt; if(Refcnt <decrement) { Throw NewIllegalreferencecountexception (refcnt,-decrement); } if(Refcntupdater.compareandset ( This, refcnt, refcnt-decrement)) { if(refcnt = =decrement) {deallocate (); return true; } return false; } } } protected Abstract voiddeallocate ();}
For bytebuf I/O operations, the writebyte (byte[] bytes) readbyte (byte[] bytes) are often used for two types of
Because BYTEBUF supports a variety of bytes objects, such as OutputStream, Gatheringbytechannel, Bytebuffer, BYTEBUF, etc.,
We only use two or three commonly used APIs to do analysis, the other logic is similar
If the reader is impressed, usually the bottom is only responsible for the process control, implementation to the application layer/subclass processing, Abstractbytebuf.class Writebyte/readbyte is also this way of processing
Public classUnpooledheapbytebufextendsAbstractreferencecountedbytebuf {//Dispenser Private FinalBytebufallocator Alloc; //Data byte[] array; //temporary bytebuffer, for internal caches PrivateBytebuffer Tmpniobuf; Privateunpooledheapbytebuf (Bytebufallocator alloc,byte[] Initialarray,intReaderindex,intWriterindex,intmaxcapacity) { //omit part of the code from the same boundary processing Super(maxcapacity); This. Alloc =Alloc; Array=Initialarray; This. Readerindex =Readerindex; This. Writerindex =Writerindex; } //Get Bytebuffer capacity@Override Public intcapacity () {ensureaccessible (); returnArray.Length; } @Override Public BooleanHasArray () {return true; } //Get Raw Data@Override Public byte[] Array () {ensureaccessible (); returnArray; } //expansion/reduction capacity@Override PublicBytebuf Capacity (intnewcapacity) {ensureaccessible (); //newcapacity parameter boundary judgment if(Newcapacity < 0 | | newcapacity >maxcapacity ()) { Throw NewIllegalArgumentException ("newcapacity:" +newcapacity); } intOldcapacity =Array.Length; //expansion processing, direct CP to the new array if(Newcapacity >oldcapacity) { byte[] NewArray =New byte[newcapacity]; System.arraycopy (Array,0, NewArray, 0, Array.Length); SetArray (NewArray); } Else if(Newcapacity <oldcapacity) { //Volume reduction processing//There are two kinds of treatment here .//1.readerIndex > Newcapacity Description There is also data unhandled directly readerindex,writerindex equal newcapacity//2. Otherwise writerindex =math.min (writerindex,newcapacity), take the minimum value, and then copy the data directly//It can be seen that netty processing exceeds readerindex, Writerindex limit directly discard data ... byte[] NewArray =New byte[newcapacity]; intReaderindex =Readerindex (); if(Readerindex <newcapacity) { intWriterindex =Writerindex (); if(Writerindex >newcapacity) {Writerindex=newcapacity This. Writerindex =Writerindex; } system.arraycopy (Array, Readerindex, NewArray, Readerindex, Writerindex-Readerindex); //system.arraycopy (copy source array, source group start coordinates, target array, target array start coordinates, copy data length); } Else { This. Readerindex =newcapacity; This. Writerindex =newcapacity; } setarray (NewArray); } return This; }}
Not finished with the waiter .....
[Weave message Frame] [Netty Source Analysis]11 Unpooledheapbytebuf and Bytebufallocator