在开始文章之前,我这里暂且认为大家曾经明确了 JVM 创建对象调配内存地址的流程,也晓得 JVM 内存划分。基于人道主义我还是放一张图吧,大家对照着看。
JVM 内存构造
堆内存划分构造
堆区分配内存是否存在多线程平安问题?
答:可能存在;
new Object();
上述操作咱们都晓得它最终须要在堆内存中开拓一块内存空间,那么想这么一个问题,堆区是所有线程共享的,那么在 JVM 频繁创建对象的时候,并发状况下在堆内存中开拓空间是不是存在平安问题。
那么为了解决这个问题咱们首先想到的就是加锁,然而加锁存在一个问题,就是影响性能。
TLAB 呈现(Thread Local Allocation Buffer)
基于下面的问题,从而引出了 TLAB,强行翻译一下就是 线程本地调配缓冲区,首先呢先看张图
申明:在堆内存中调配空间,首先是在 eden 区进行调配,并不是间接调配在老年代,内存调配完结之后,没进行一次 Yong GC,如果对象没有被回收,那么他的存活次数就会 +1,如果这个次数达到 15 次,那么这个对象降职到老年代。
那么咱们晓得了对象调配首先是在 eden 区进行的,那么也不难理解下面的图,咱们在 eden 区域划分进去一块区域,咱们称之为 TLAB,每一个 TLAB 都是现成公有的,那么并发创建对象的时候其实也就不须要进行加锁这样的操作了,这样现成平安问题就解决了。
如果调配的这些 TLAB 空间被应用完了或者对象所须要额内存空间大于 TLAB 所能提供的空间,那么只能在专用的 eden 区或者老年代分配内存空间了。
总结
- 1、JVM 首选 TLAB 进行内存空间的调配;
- 2、TLAB 占用整个 eden 区域的 1%,这个值也能够通过参数自定义;
通过这个问题也能够推理出另外一个问题,堆区在严格意义上说不是线程共享的。