jvm中的TLAB
一. 回顾
前面了解了jvm中的逃逸分析,逃逸分析中有涉及栈分配,今天了解一下TLAB
(Thread Local Allocation Buffer)。
本文仅供自己参考,如有错误请指正
参考自:
二. TLAB的来源
指针碰撞
2.1 指针碰撞
详情见Java的指针碰撞简介
2.2 TLAB的出现
为了避免指针碰撞,TLAB出现了!!!
TLAB,Thread Local Allocation Buffer,线程本地分配缓存区。这是一个线程私有的分配区域。从堆中划分确定大小的内存作为TLAB。
jvm参数:
解释 | jvm参数 |
---|---|
开启TLAB | -XX:+UseTLAB |
打印TLAB详细信息 | -XX:+PrintTLAB |
指定分配给每个线程的TLAB大小 | -XX:+TLABSize |
如果设置了jvm参数-XX:+UseTLAB
,在线程初始化时,会向堆申请一个确定大小的内存(即TLAB,缺省情况下,TLAB仅占Eden区的1%)作为当前线程私有的空间,线程运行过程中,如果需要分配内存,会在自己的TLAB上分配,这样就不存在申请内存的竞争。
2.3 TLAB的本质
有三个管理区域的指针:start;top;end
指针 | 解释 |
---|---|
start 、end
|
每个线程都会从Eden区拿到一块空间,start与end作占位用的,即start与end之间的空间不允许被其他线程申请(允许访问,不允许申请) |
总结:TLAB只是允许每个线程都有分配指针,其他线程仍然可以访问TLAB里面的对象。即可访问,但不可申请内存。当一个TLAB满了(即top指针指到了end指针指向的位置),会申请一个新的TLAB。旧TLAB里面的对象仍留在原地,它们无法感知自己是否是从TLAB分配出来的,它们只关心是自己在Eden区分配的。
如下:
2.4 TLAB的缺点
- 因为TLAB很小,缺省情况下是Eden区的1%,所以放不下大对象。(比如TLAB有100KB,此时来了个110KB的对象)
- TLAB剩余的空间不足以存放新new出来的对象,会有点浪费。(比如TLAB有100KB,剩余20KB可用,此时来了一个30KB的对象)
因此开发人员设计了一个最大浪费空间:
- 当剩余空间<最大浪费空间 时,该TLAB所属的线程会重新向Eden申请一个TLAB(旧的TLAB不作清理,会留在原地)。创建对象时发现还是不够空间,则此对象太大,直接去Eden区创建(即TLAB外的Eden区域)。
- 当剩余空间>最大浪费空间时,不重新申请TLAB,直接去Eden创建对象。
- Eden区不够内存了,堆的Eden区开始GC。
- 因为TLAB允许空间浪费,所以会存在很多不连续的空间(空间碎片),以后还需要人整理。