栈上分配和TLAB
2016-10-14 16:06
85 查看
栈上分配
JVM允许将线程私有的对象打散分配在栈上,而不是分配在堆上。分配在栈上的好处是可以在函数调用结束后自行销毁,而不需要垃圾回收器的介入,从而提高系统性能。栈上分配的一个技术基础是进行逃逸分析,逃逸分析的目的是判断对象的作用域是否有可能逃逸出函数体。另一个是标量替换,允许将对象打散分配在栈上,比如若一个对象拥有两个字段,会将这两个字段视作局部变量进行分配。
只能在server模式下才能启用逃逸分析,参数
-XX:DoEscapeAnalysis启用逃逸分析,参数
-XX:+EliminateAllocations开启标量替换(默认打开)。在JDK 6u23版本之后,HotSpot中默认就开启了逃逸分析,可以通过选项
-XX:+PrintEscapeAnalysis查看逃逸分析的筛选结果。
TLAB
TLAB的全称是Thread Local Allocation Buffer,即线程本地分配缓存区。这是一个线程专用的内存分配区域。由于对象一般会分配在堆上,而堆是全局共享的。因此在同一时间,可能会有多个线程在堆上申请空间。因此,每次对象分配都必须要进行同步,而在竞争激烈的场合分配的效率又会进一步下降。JVM使用TLAB来避免多线程冲突,每个线程使用自己的TLAB,这样就保证了不使用同步,提高了对象分配的效率。
TLAB本身占用eden区空间,在开启TLAB的情况下,虚拟机会为每个Java线程分配一块TLAB空间。参数
-XX:+UseTLAB开启TLAB,默认是开启的。TLAB空间的内存非常小,缺省情况下仅占有整个Eden空间的1%,当然可以通过选项
-XX:TLABWasteTargetPercent设置TLAB空间所占用Eden空间的百分比大小。
由于TLAB空间一般不会很大,因此大对象无法在TLAB上进行分配,总是会直接分配在堆上。TLAB空间由于比较小,因此很容易装满。比如,一个100K的空间,已经使用了80KB,当需要再分配一个30KB的对象时,肯定就无能为力了。这时虚拟机会有两种选择,第一,废弃当前TLAB,这样就会浪费20KB空间;第二,将这30KB的对象直接分配在堆上,保留当前的TLAB,这样可以希望将来有小于20KB的对象分配请求可以直接使用这块空间。实际上虚拟机内部会维护一个叫作refill_waste的值,当请求对象大于refill_waste时,会选择在堆中分配,若小于该值,则会废弃当前TLAB,新建TLAB来分配对象。这个阈值可以使用TLABRefillWasteFraction来调整,它表示TLAB中允许产生这种浪费的比例。默认值为64,即表示使用约为1/64的TLAB空间作为refill_waste。默认情况下,TLAB和refill_waste都会在运行时不断调整的,使系统的运行状态达到最优。如果想要禁用自动调整TLAB的大小,可以使用
-XX:-ResizeTLAB禁用ResizeTLAB,并使用
-XX:TLABSize手工指定一个TLAB的大小。
-XX:+PrintTLAB可以跟踪TLAB的使用情况。一般不建议手工修改TLAB相关参数,推荐使用虚拟机默认行为。
那么总结一下虚拟机对象分配流程:首先如果开启栈上分配,JVM会先进行栈上分配,如果没有开启栈上分配或则不符合条件的则会进行TLAB分配,如果TLAB分配不成功,再尝试在eden区分配,如果对象满足了直接进入老年代的条件,那就直接分配在老年代。
相关文章推荐
- Java中的逃逸分析和TLAB以及Java对象分配
- Java中的逃逸分析和TLAB以及Java对象分配
- 栈分配与TLAB
- Java中的逃逸分析和TLAB以及Java对象分配
- Java常见面试题—栈分配与TLAB
- C与C++的内存分配方式比较
- [虚拟机VMware_Ubuntu]VMware虚拟机Ubuntu分配Android开发所需虚拟磁盘空间
- 内存分配
- Android 内存分配跟踪工具(Allocation tracker)
- C++primer 4.3 动态数组、动态内存分配(C里面)malloc、 free
- Redis源码剖析和注释(二十五)--- Redis Cluster 的通信流程深入剖析(载入配置文件、节点握手、分配槽)
- FPGA管教分配问题及注意事项
- 处理字符串时如何选择buffer的大小和分配方式 - 看看 redis 是怎么做的
- Memcached内存分配机制—— Slab Allocator
- 深入Java核心 Java内存分配原理精讲
- ifconfig 下 没有eth0,无法DHCP分配IP
- 动态内存分配
- 彩球分配问题:共有12个彩球,4个红的,4个白的,4个黄的,从中挑出8个球放入3个不同的口袋(口袋编号分别为a、b、c)编写程序打印输出所有可能的放法。
- linux内核调度算法(2)--CPU时间片如何分配
- 如何给mysql用户分配权限