Netty Unpooledheapbytebuf Source Analysis

Source: Internet
Author: User

Unpooledheapbytebuf is a byte buffer based on heap memory allocation, not implemented based on the object pooling technique, which means that a new unpooledheapbytebuf is created for each I/O read/write. The allocation and recycling of large chunks of memory can have a certain impact on performance, but it can be less costly to compare to the application and release of out-of-heap memory.

Relative and POOLEDHEAPBYTEBUF,UNPOOLEDHEAPBYTEBUF implementation principle is more simple, also not prone to memory management problems, in the case of satisfying performance, try to use UNPOOLEDHEAPBYTEBUF.

1. member Variables
Private Final Bytebufallocator Alloc; // aggregates a bytebufallocator for unpooledheapbytebuf memory allocation Private byte [] array; // byte array as buffer Private Bytebuffer Tmpniobuf; // conversion to implement Netty Bytebuf to JDK bytebuffer

In fact, it is also possible to replace a byte array with the Bytebuffer of the JDK, and the root cause of using a byte array directly is to improve performance and make bit operations easier. The bytebuffer underlying implementation of the JDK is also a byte array, as follows.

 Public Abstract classBytebufferextendsBufferImplementsComparable<bytebuffer>{    //These fields is declared here rather than in Heap-x-buffer in order to//Reduce the number of virtual method invocations needed to access these//values, which is especially costly when coding small buffers. //    Final byte[] HB;//non-null only for heap buffers    Final intoffset; BooleanIsReadOnly;//Valid only for heap buffers
2. Dynamically expanding Buffers
@Override PublicBytebuf Capacity (intnewcapacity)    {ensureaccessible (); if(Newcapacity < 0 | | newcapacity >maxcapacity ()) {        Throw NewIllegalArgumentException ("newcapacity:" +newcapacity); }    intOldcapacity =Array.Length; if(Newcapacity >oldcapacity) {        byte[] NewArray =New byte[newcapacity]; System.arraycopy (Array,0, NewArray, 0, Array.Length);    SetArray (NewArray); } Else if(Newcapacity <oldcapacity) {        byte[] NewArray =New byte[newcapacity]; intReaderindex =Readerindex (); if(Readerindex <newcapacity) {            intWriterindex =Writerindex (); if(Writerindex >newcapacity) {Writerindex (Writerindex=newcapacity); } system.arraycopy (Array, Readerindex, NewArray, Readerindex, Writerindex-Readerindex); } Else{setindex (newcapacity, newcapacity);    } setarray (NewArray); }    return  This;}
/***/protectedfinalvoid  ensureaccessible ()    {  If (refcnt () = = 0)        {thrownew illegalreferencecountexception (0);}    } 

The ingress of the method first validates the new capacity, and throws a IllegalArgumentException exception if it is greater than the capacity limit or less than 0.

Determine whether the new capacity value is greater than the current buffer capacity, if it is greater than the need to dynamically expand, through byte[] NewArray = new Byte[newcapacity]; Create a new buffer byte array, and then pass the System.arraycopy makes a memory copy, copies the old byte array into the newly created byte array, and finally calls SetArray (NewArray), replacing the old byte array.

Private void setarray (byte[] initialarray) {    = initialarray;     NULL ;}

After dynamic expansion is complete, you need to set the original view Tmpniobuf to empty.

If the new capacity is less than the current buffer capacity, it does not need to be expanded dynamically, but the current buffer needs to be truncated to create a new sub-buffer. First determine if the next read index is less than the new capacity value, if the write index is less than the new capacity value, if it is greater than the write index is set to the new capacity value (prevent out of bounds). After the write index is updated, the current readable byte array is copied to the newly created sub-buffer by System.arraycopy.System.arraycopy(array, readerIndex, newArray, readerIndex, writerIndex - readerIndex);

If the new capacity value is less than the read index, it means that no readable byte array needs to be copied into the newly created buffer, and the read-write index will be the new capacity value. Finally, the SetArray method is called to replace the original byte array.

3. Byte array replication
@Override  Public Bytebuf setbytes (intbyteintint  length) {    Checksrcindex (index, length, Srcindex, src.length);    System.arraycopy (SRC, srcindex, array, index, length);     return  This ;}

First do the legitimacy check.

 protected  final  void  checksrcindex (int  index, int  length, int  srcindex, int   srccapacity) {CheckIndex (index, length);  if  (Srcindex < 0 | | srcindex > srccapacity- Length" { throw  new   Indexoutofboundsexception (String.Format (" Srcindex:%d, Length:%d (Expected:range (    0,%d)) "

Checks the value of index,length, if less than 0, throws a IllegalArgumentException exception, and then the sum of the two is judged, if the capacity of the buffer is greater than the indexoutofboundsexception exception is thrown. Srcindex and srccapacity are similar. After the checksum is passed, the system.arraycopy (SRC, srcindex, array, index, length) method is called to replicate the byte array.

protected Final voidCheckIndex (intIndexintfieldlength)    {ensureaccessible (); if(Fieldlength < 0) {        Throw NewIllegalArgumentException ("Length:" + fieldlength + "(expected: >= 0)"); }    if(Index < 0 | | index > Capacity ()-fieldlength) {        Throw Newindexoutofboundsexception (String.Format ("Index:%d, Length:%d (expected:range (0,%d))", index, fieldlength, Capacity ())); }}

Note: butebuf read-write buffers with set and get begin without modifying read-write indexes.

4. Convert to JDK Bytebuffer

Bytebuffer is based on a byte array implementation, and NiO's Bytebuffer provides the Wrap method, which converts a byte array into a Bytebuffer object.

/*** Wraps a byte array into a buffer.     * * <p> The new buffer would be backed by the given byte array;  * That's, modifications to the buffer would cause the array to be modified * and vice versa. The new buffer ' s capacity would be * <TT>ARRAY.LENGTH</TT> and its position'll be <tt>offset</tt>  ;, its limit * would be <tt>offset + length</tt>, and its mark would be undefined. its * {@link#array backing Array} would be is the given array, and * its {@link#arrayOffset Array Offset} would be zero. </p> * *@paramArray * The array that would back the new buffer * *@paramOffset * The offset of the subarray to being used; must be non-negative and * no larger than &L  T;tt>array.length</tt>.     The new buffer ' s position * would be set to this value. *     * @paramlength * The length of the subarray to be used;     * Must be non-negative and no larger than * <TT>ARRAY.LENGTH-OFFSET</TT>.     * The new buffer ' s limit would be set to <tt>offset + Length</tt>. *     * @returnThe new byte buffer * *@throwsindexoutofboundsexception * If The preconditions on the <tt>offset</tt> and <tt>lengt h</tt> * Parameters don't hold*/     Public StaticBytebuffer Wrap (byte[] Array,intOffsetintlength) {        Try {            return Newheapbytebuffer (array, offset, length); } Catch(IllegalArgumentException x) {Throw Newindexoutofboundsexception (); }    }

Unpooledheapbytebuf.java

@Override  Public Bytebuffer niobuffer (intint  length) {    ensureaccessible ();     return bytebuffer.wrap (array, index, length). Slice ();

The slice method of Bytebuffer was called, because each call to Niobuffer creates a new bytebuffer, so the slice method here does not have the effect of reusing buffers, only guarantees the independence of read-write indexes.

5. Methods related to subclasses

Isdirect method: If the underlying heap memory implements the BYTEBUF, returns false,

@Override  Public Boolean Isdirect () {    returnfalse;}

HasArray method: Because Unpooledheapbytebuf is implemented based on a byte array, returns True

@Override  Public Boolean HasArray () {    returntrue;}

Array method: Because Unpooledheapbytebuf is based on a byte array implementation, the return value is an internal byte array member variable. Before calling the array method, you can first use the HasArray method to determine if the return false indicates that the current BYTEBUF does not support the array method.

@Override  Public byte [] Array () {    ensureaccessible ();     return Array;}

Netty Unpooledheapbytebuf Source Analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.