1.首先聲明,netty內(nèi)部通過ByteBufAllocator來使用bytebuf,他也推薦使用者按照這樣方式使用。不僅僅因?yàn)閚etty在這個里面幫我們實(shí)現(xiàn)了大部分我們想要的bytebuf,更重要的是netty還對于我們的bytebuf分配進(jìn)行了統(tǒng)計和內(nèi)存泄漏檢測提供了便利。
2.本篇文章主要關(guān)注bytebuf是如何生成的,對于為啥用bytebuf取代bytebuffer 大家可以去關(guān)注其他博客,主要還是原來的bytebuffer的api操作比較麻煩而且少。
3.那么我們主要關(guān)注堆內(nèi)非池化bytebuf,堆內(nèi)池化bytebuf,堆外池化bytebuf和堆外非池化bytebuf。其中對于堆內(nèi)的bytebuf來說,其都是通過byte數(shù)組來存儲數(shù)據(jù),對于堆外的bytebuf來說其是通過directbytebuffer來保存數(shù)據(jù)
4.非池化bytebuf:UnpooledUnsafeHeapByteBuf,UnpooledHeapByteBuf
一、UnpooledUnsafeHeapByteBuf繼承了UnpooledHeapByteBuf其中主要是從寫了UnpooledHeapByteBuf的set和get方法即write和read,UnpooledUnsafeHeapByteBuf通過unsafe獲取到我們bytebuf內(nèi)部數(shù)組在內(nèi)存中的地址
然后直接操作地址,這樣的效率比我們調(diào)用數(shù)組的api方法更快。
二、應(yīng)該他們都繼承了AbstractReferenceCountedByteBuf所以其release方法釋放堆內(nèi)非池化的bytebuf是將數(shù)組與當(dāng)前bytebuf對象斷開聯(lián)系即可(也就是將我們bytebuf中對數(shù)組的引用設(shè)置為null)5.堆內(nèi)池化bytebuf:PooledUnsafeHeapByteBuf,PooledHeapByteBuf
一、對于pool,netty優(yōu)先從threadlocal獲取PoolArena,對于堆內(nèi)的就是DirectArena
二、然后依靠PoolArena去分配bytebuf對象和bytebuf內(nèi)部真正持有數(shù)據(jù)的對象對于堆內(nèi)就是數(shù)組
三、對于bytbuf的獲取是依靠RECYCLER,而數(shù)組的大小分配則是依據(jù)內(nèi)存的大小來分,具體原理稍后會細(xì)說下。
四、對于PooledUnsafeHeapByteBuf,PooledHeapByteBuf的區(qū)別還是通過unsafe來存取數(shù)據(jù)的區(qū)別,但是他們釋放的方法卻都是一樣都是調(diào)用poolArea去回收數(shù)組內(nèi)存,而對于bytebuf對象本身則放入recycle里面。6.堆外非池化bytebuf:UnpooledUnsafeNoCleanerDirectByteBuf,UnpooledDirectByteBuf,UnpooledUnsafeDirectByteBuf
一、UnpooledDirectByteBuf:是直接生產(chǎn)一個directbytebuffer對象,然后釋放也是依靠directbytebuffer內(nèi)部的cleaner對象(我們通過反射獲取到cleaner對象然后調(diào)用其clean方法,而不是依靠虛引用來調(diào)用clean方法因?yàn)樘撘没厥諆?nèi)存不及時會導(dǎo)致oom)。
二、UnpooledUnsafeDirectByteBuf和UnpooledDirectByteBuf大部分一樣,不一樣地方在于他獲悉了其directbytebuffer的內(nèi)置地址,然后通過unsafe操作該對象。這樣的好處就是讀取速度快。
三、而UnpooledUnsafeNoCleanerDirectByteBuf與UnpooledUnsafeDirectByteBuf相似,區(qū)別在于前者沒有cleaner對象(因?yàn)橥ㄟ^反射調(diào)用了DirectByteBuffer的其他構(gòu)造函數(shù)),所以其內(nèi)存釋放需要借助于unsafe,其實(shí)上述的cleaner調(diào)用clean方法 其底層也是調(diào)用unsafe的方法。
- 7.堆外池化bytebuf:PooledUnsafeDirectByteBuf和PooledDirectByteBuf
一、到這邊就沒有好說的了對于pool的操作類似于堆內(nèi)池化bytebuf,至于涉及到的unsafe,cleaner 我也在前面講完了。
補(bǔ)充:對于pool的bytebuf 堆內(nèi)的會預(yù)先申請一系列字節(jié)數(shù)組,這些數(shù)組可以按照大小分為tiny,small,nomarl,而對于huge則直接分配 分配完了直接回收。同理對于堆外內(nèi)存就是預(yù)先申請一系列的directbytebuf,每個directByte含有的堆外內(nèi)存大小不等。那么我們回收的時候也是把bytebuf對象放入recycler,但是其內(nèi)部字節(jié)數(shù)組或者directbytebuffer則歸還給PoolArea
--bytebuf劇終!!