Java对象空间分配流程

对象空间分配流程如下:
 
针对这个流程,分别解释一下每一个选项的使用场景。

栈上分配:

栈上分配的基础在于逃逸分析,逃逸分析可以得到三种对象的逃逸状态。
  • 全局逃逸:一个对象的引用逃出了方法或者线程。
  • 参数级逃逸:在方法调用过程中传递对象的引用到另一个方法。
  • 没有逃逸:一个可以进行标量替换的对象。
基于分析结果,一般有如下3种优化:
  • 堆分配对象变成栈分配对象,栈分配的对象,不需要gc,在方法离开此方法栈后,栈空间的数据随之销毁。
  • 消除同步,逃逸分析可以判断出某个对象是否始终只被一个线程访问,如果只被一个线程访问,那可以取消对其的同步保护,可以较大的提升并发程度与性能。
  • 矢量替代,如果发现对象的内存存储结构不需要连续进行的话,就可以将对象的部分甚至全部都保存在CPU寄存器内。
 
逃逸分析:
开启:-XX:+DoEscapeAnalysis
关闭:-XX:-DoEscapeAnalysis
标量替换:
开启:-XX:+EliminateAllocations
关闭:-XX:-EliminateAllocations
锁消除:
开启:-XX:+EliminateLocks
关闭:-XX:-EliminateLocks
在jdk1.8都是默认开启的。
栈空间的大小,对栈上分配有一定的影响,但栈空间更多的是影响线程调用栈深度与可以创建的线程数量。
 

TLAB分配:

一般的对象分配内存,都是在新生代进行空间申请的。在多个线程都在申请空间时,每次对象分配都必须进行同步。竞争激烈的场合分配的效率又会进一步下降。TLAB是一个存在于eden区的线程独享内存区域,主要用于降低在新生代分配对象时的内存竞争,提升对象分配的效率。
默认开启,也可以使用-XX:+UseTLA参数主动开启。
TLAB的refill操作包括如下几个动作:
  • 将当前TLAB抛弃,这个过程中最重要的是将TLAB末尾尚未分配给Java对象的空间分配成一个filler object;
  • 从Eden区新分配一块空白的空间(可能存在失败);
  • 将新分配的空间范围记录到ThreadLocalAllocBuffer里。
TLAB refill不成功,就会触发YGC。 
原文地址:https://www.cnblogs.com/asfeixue/p/9267925.html