揭開JVM中TLAB中的神秘面紗
本文轉(zhuǎn)載自微信公眾號「一個程序員的成長」,作者一個程序員的成長。轉(zhuǎn)載本文請聯(lián)系一個程序員的成長公眾號。
在開始文章之前,我這里暫且認(rèn)為大家已經(jīng)明白了JVM創(chuàng)建對象分配內(nèi)存地址的流程,也知道JVM內(nèi)存劃分?;谌说乐髁x我還是放一張圖吧,大家對照著看。
JVM內(nèi)存結(jié)構(gòu)
堆內(nèi)存劃分結(jié)構(gòu)
堆區(qū)分配內(nèi)存是否存在多線程安全問題?
答:可能存在;
new Object();
上述操作我們都知道它最終需要在堆內(nèi)存中開辟一塊內(nèi)存空間,那么想這么一個問題,堆區(qū)是所有線程共享的,那么在JVM頻繁創(chuàng)建對象的時候,并發(fā)情況下在堆內(nèi)存中開辟空間是不是存在安全問題。
那么為了解決這個問題我們首先想到的就是加鎖,但是加鎖存在一個問題,就是影響性能。
TLAB出現(xiàn)(Thread Local Allocation Buffer)
基于上面的問題,從而引出了TLAB,強(qiáng)行翻譯一下就是線程本地分配緩沖區(qū),首先呢先看張圖
聲明:在堆內(nèi)存中分配空間,首先是在eden區(qū)進(jìn)行分配,并不是直接分配在老年代,內(nèi)存分配結(jié)束之后,沒進(jìn)行一次Yong GC,如果對象沒有被回收,那么他的存活次數(shù)就會 +1,如果這個次數(shù)達(dá)到15次,那么這個對象晉升到老年代。
那么我們知道了對象分配首先是在eden區(qū)進(jìn)行的,那么也不難理解上面的圖,我們在eden區(qū)域劃分出來一塊區(qū)域,我們稱之為TLAB,每一個TLAB都是現(xiàn)成私有的,那么并發(fā)創(chuàng)建對象的時候其實(shí)也就不需要進(jìn)行加鎖這樣的操作了,這樣現(xiàn)成安全問題就解決了。
如果分配的這些TLAB空間被使用完了或者對象所需要額內(nèi)存空間大于TLAB所能提供的空間,那么只能在公用的eden區(qū)或者老年代分配內(nèi)存空間了。
總結(jié)
- 1、JVM首選TLAB進(jìn)行內(nèi)存空間的分配;
- 2、TLAB占用整個eden區(qū)域的1%,這個值也可以通過參數(shù)自定義;
通過這個問題也可以推理出另外一個問題,堆區(qū)在嚴(yán)格意義上說不是線程共享的。