大家好,我是树哥。我们在学习G1收集器的时候,一般都会接触到TLAB和PLAB这两个名词。它们都是为了提高内存分配效率而存在的,但是它们和在栈上分配有什么区别呢?今天就让舒哥带大家来一盘。栈上的分配对Java虚拟机的内存结构稍有了解的同学都知道,Java虚拟机中有两个关键的存储数据节点,即:堆和栈。堆是所有线程共享的一块内存,几乎所有的对象都分配在这块内存中。栈是线程自己私有的,只存放线程自身的局部变量等信息。每个线程都有自己的栈,线程之间不能共享栈信息。一般来说,如果每个线程都有一个新的对象,它会向JVM申请在堆上创建相应的对象,线程的栈中存放着一个指向堆对象的指针。每当一个线程要创建一个对象时,首先请求JVM,然后请求JVM坐标,创建完成后再告诉线程,线程最后将引用压入栈中。在对象创建过程中,堆与栈的关系就像火车中央调度室与列车的关系。线程每次需要分配内存空间时,都需要去堆中申请空间,这会消耗大量的时间和精力。这时候有人发现,线程的某些对象其实是其他人无法访问的,而且放在堆中似乎也没有太大的作用。于是他提出:对于这些其他线程不会访问的对象,是否可以让线程分配自己的栈空间呢?这不是可以节省很多交互时间吗?这个方法真好。如果能够实现的话,应该可以改善对象创建的时间,提高虚拟机的运行效率。但问题是:我怎么知道哪些对象可以分配到栈上,哪些不可以呢?其实聪明的软件工程师早就解决了这个问题,他们还起了一个新名字:逃逸分析。那么什么是逃逸分析呢?从字面上理解,逃逸分析的目的是判断对象的作用域是否有可能逃出函数体。例如,下面的代码显示了一个转义对象:privatestaticUseruser;privatestaticvoidhello(){u=newUser();u.name="java.top.select";u.website="http://www.shuyi.me";}对象实例user是类的成员变量,可以被任何线程访问,所以属于转义对象。但是如果我们稍微改变一下代码,这个对象就可以是无线程的了。privatestaticvoidhello(){用户u=newUser();u.name="java.top.select";u.website="http://www.shuyi.me";}可以看到user实例的函数该字段只存在于hello函数中,不会被其他线程访问,也不会被访问到。所以用户实例对象的作用域只是在这个函数中,所以并没有逃逸。对于这种情况,虚拟机可能会在栈而不是堆上分配它。看到这里,相信很多人应该明白栈上的分配是什么了。简单点说,就是把本该在堆中分配的对象分配到线程的私有栈上。这样就减轻了垃圾回收的压力,提高了虚拟机的运行效率。TLABTLAB(ThreadLocalAllocationBuffer),即线程本地分配缓冲区。这是一个线程专有的内存分配区,TLAB占用eden区的空间。当启用TLAB时(默认启用),JVM会为每个线程分配一个TLAB区域。那么为什么需要TLAB?这是为了加速对象分配!由于对象一般分配在堆上,而堆是线程共享的,可能会有多个线程在堆上申请空间,每次对象分配都必须线程同步,这样会降低内存分配的效率。考虑到对象分配是一个很常见的操作,JVM使用TLAB等线程游荡区来避免多线程冲突,提高对象分配效率。为了不造成Eden区被填满,TLAB空间一般不会太大。因此,大对象可能无法在TLAB中分配,而只能直接在堆上分配。这其实是一种折衷的设计理念,因为大部分分配的对象都比较小,所以TLAB空间可以满足大部分需求。PLABPLAB(PromotionLocalAllocationBuffers),即提升本地分配缓冲区。PLAB的作用类似于TLAB。都是为了加快对象分配效率,避免多线程竞争而生的。只是PLAB应用于对象向Survivor区或者老年代的提升。与TLAB类似,每个线程都有自己的PLAB区域。对象内存分配过程与栈上和TLAB上的分配有一定的关系。分配对象内存时,会先尝试在栈上分配,然后尝试分配TLAB,然后判断是否可以直接进入老年代,如果失败最后在eden区分配,如下图.图片来自网络总结了解了栈上、TLAB、PLAB上的分配之后,我们基本上可以清楚地回答下面的问题。什么是栈上分配,它解决了什么问题?栈上分配是指直接在线程栈帧中分配对象,而不是在堆中。主要是为了解决多线程对象分配效率低下的问题。通过在栈上分配内存,避免了多线程之间的冲突,提高了对象分配的效率。但需要注意的是,它只能分配较小的对象,并且该对象一定不能被其他对象线程引用。什么是TLAB,它解决什么问题?TLAB指的是线程局部分配缓存,对应Eden区中的某个区域,但是这个区域只能被本线程使用。堆栈上的分配和TLAB有什么区别?TLAB可以理解为栈上分配的升级版本。分配在栈上的对象只能被线程自己访问,而TLAB对象可以被其他对象读取,但不应该被操作。通过TLAB,解决了一些需要多线程访问的对象分配效率问题,进一步提高了JVM的对象分配效率。什么是PLAB,它解决了什么问题?PLAB是为了提高对象提升到Survivor区或老年代时的分配效率。它的优化思路和TLAB类似,只是应用的地方不同。参考资料JVMobjectallocation:on-stackallocation&TLABallocation-掘金栈上分配技术,这么高端的技术是什么?JVM内存分配机制中栈分配和TLAB的区别-腾讯云开发者社区-腾讯云
