深入理解Java虚拟机之对象的内存分配续

首先强烈感谢我的两位同学,广州微笑和杭州青果。这篇博客灵感来自于他们。

上一篇博客说了,Java对象的内存分配中在堆空间中分配内存的几条普遍规则,当然也说了,在分配到堆内存之前也进行了其它方面的尝试,那今天就说一说jvm这些的尝试

首先一张图看jvm内存分配的选择

深入理解Java虚拟机之对象的内存分配续

从上图可知,jvm首先尝试在栈上分配内存,如果栈上分配内存失败了,再尝试在TLAB上尝试分配

如果分配失败了就判断这个对象可否进入老年代,如果可以就将其放入老年代,否则再分配到eden上

问题1:不是说好的绝大多数都在堆里面吗?为什么jvm会尝试着去栈空间里分配内存呢?

   堆空间中的对象是线程共享的,只要拥有这个对象的引用,都可以操作这个对象和获取该对象中存储的数据,Java垃圾回收机制回收对象时是要耗费资源(时间和空间)的,但是如果能确定一个对象不会逃逸出某个方法,且这个对象不大(即该对象占用内存比较小),就可以尝试分配栈空间给这个对象,把这个对象放入栈空间,准确的说是某个方法的栈帧,当某个方法执行完了,该对象也随着这个方法栈帧的出栈而销毁,对于方法中的局部对象正好符合这个特点,那么如果尝试着把这些对象分配到栈帧中,大量的对象随着出栈而销毁,所以,垃圾收集器的压力会小很多。


问题2: TLAB是什么?有什么用?

TLAB(Thread Local Allocation Buffer)即线程本地缓冲,jvm会在堆空间的eden上分配一块线程私有的内存(默认占eden的1%),Java程序会存在大量的朝生夕死的线程私有的小对象,而这些小对象也适合被快速回收,所以将这些对象分配到这部分线程私有的内存中,没有锁开销,效率比较高!

如果TLAB上分配失败则再考虑到eden或者老年代分配,具体请看 Java对象的内存分配