TLAB是虚拟机在堆内存的eden划分出来的一块专用空间,是线程专属的。在虚拟机的TLAB功能启动的情况下,在线程初始化时,虚拟机会为每个线程分配一块TLAB空间,只给当前线程使用,这样每个线程都单独拥有一个空间,如果需要分配内存,就在自己的空间上分配,这样就不存在竞争的情况,可以大大提升分配效率。这里值得注意的是,我们说TLAB是线程独享的,但是只是在“分配”这个动作上是线程独享的,至于在读取、垃圾回收等动作上都是线程共享的。而且在使用上也没有什么区别

也就是说,虽然每个线程在初始化时都会去堆内存中申请一块TLAB,并不是说这个TLAB区域的内存其他线程就完全无法访问了,其他线程的读取还是可以的,只不过无法在这个区域中分配内存而已。

并且,在TLAB分配之后,并不影响对象的移动和回收,也就是说,虽然对象刚开始可能通过TLAB分配内存,存放在Eden区,但是还是会被垃圾回收或者被移到Survivor Space、Old Gen等。

还有一点需要注意的是,我们说TLAB是在eden区分配的,因为eden区域本身就不太大,而且TLAB空间的内存也非常小,默认情况下仅占有整个Eden空间的1%。所以,必然存在一些大对象是无法在TLAB直接分配。

遇到TLAB中无法分配的大对象,对象还是可能在eden区或者老年代等进行分配的,但是这种分配就需要进行同步控制,这也是为什么我们经常说:小的对象比大的对象分配起来更加高效。

TLAB带来的问题

虽然在一定程度上,TLAB大大的提升了对象的分配速度,但是TLAB并不是就没有任何问题的。

前面我们说过,因为TLAB内存区域并不是很大,所以,有可能会经常出现不够的情况。在《实战Java虚拟机》中有这样一个例子:

比如一个线程的TLAB空间有100KB,其中已经使用了80KB,当需要再分配一个30KB的对象时,就无法直接在TLAB中分配,遇到这种情况时,有两种处理方案:

1、如果一个对象需要的空间大小超过TLAB中剩余的空间大小,则直接在堆内存中对该对象进行内存分配。

2、如果一个对象需要的空间大小超过TLAB中剩余的空间大小,则废弃当前TLAB,重新申请TLAB空间再次进行内存分配。

以上两个方案各有利弊,如果采用方案1,那么就可能存在着一种极端情况,就是TLAB只剩下1KB,就会导致后续需要分配的大多数对象都需要在堆内存直接分配。

如果采用方案2,也有可能存在频繁废弃TLAB,频繁申请TLAB的情况,而我们知道,虽然在TLAB上分配内存是线程独享的,但是TLAB内存自己从堆中划分出来的过程确实可能存在冲突的,所以,TLAB的分配过程其实也是需要并发控制的。而频繁的TLAB分配就失去了使用TLAB的意义。

为了解决这两个方案存在的问题,虚拟机定义了一个refill_waste的值,这个值可以翻译为“最大浪费空间”。

当请求分配的内存大于refill_waste的时候,会选择在堆内存中分配。若小于refill_waste值,则会废弃当前TLAB,重新创建TLAB进行对象内存分配。

前面的例子中,TLAB总空间100KB,使用了80KB,剩余20KB,如果设置的refill_waste的值为25KB,那么如果新对象的内存大于25KB,则直接堆内存分配,如果小于25KB,则会废弃掉之前的那个TLAB,重新分配一个TLAB空间,给新对象分配内存。

TLAB使用的相关参数

TLAB功能是可以选择开启或者关闭的,可以通过设置-XX:+/-UseTLAB参数来指定是否开启TLAB分配。

TLAB默认是eden区的1%,可以通过选项-XX:TLABWasteTargetPercent设置TLAB空间所占用Eden空间的百分比大小。

默认情况下,TLAB的空间会在运行时不断调整,使系统达到最佳的运行状态。如果需要禁用自动调整TLAB的大小,可以使用-XX:-ResizeTLAB来禁用,并且使用-XX:TLABSize来手工指定TLAB的大小。

TLAB的refill_waste也是可以调整的,默认值为64,即表示使用约为1/64空间大小作为refill_waste,使用参数:-XX:TLABRefillWasteFraction来调整。

如果想要观察TLAB的使用情况,可以使用参数-XX+PringTLAB 进行跟踪。

总结

为了保证对象的内存分配过程中的线程安全性,HotSpot虚拟机提供了一种叫做TLAB(Thread Local Allocation Buffer)的技术。

在线程初始化时,虚拟机会为每个线程分配一块TLAB空间,只给当前线程使用,当需要分配内存时,就在自己的空间上分配,这样就不存在竞争的情况,可以大大提升分配效率。

所以,“堆是线程共享的内存区域”这句话并不完全正确,因为TLAB是堆内存的一部分,它在读取上确实是线程共享的,但是在内存分配上,是线程独享的。

TLAB的空间其实并不大,所以大对象还是可能需要在堆内存中直接分配。那么,对象的内存分配步骤就是先尝试TLAB分配,空间不足之后,再判断是否应该直接进入老年代,然后再确定是再eden分配还是在老年代分配。

TLAB(Thread Local Allocation Buffer)相关推荐

  1. JVM线程本地分配缓冲区(Thread Local Allocation Buffer)TLAB详解

    最近在看java性能相关方面的书籍.然后在GC调优相关的部分出现了,线程本地分配缓冲区的名词,对于它的调优级为重要,所以就梳理一下这个到底是什么?为什么他对于JVM性能如此重要. 什么是JVM线程本地 ...

  2. 在TLAB(线程本地分配缓存)上分配对象

    目录 使用TLAB性能差异 示例 分配策略 Java对象分配过程 JVM的Thread Local Allocation Buffer,即TLAB线程本地分配缓存,作用是加速分配对象空间,以前的日志里 ...

  3. 【智能算法】迭代局部搜索(Iterated Local Search, ILS)详解

    更多精彩尽在微信公众号[程序猿声] 迭代局部搜索(Iterated Local Search, ILS) 00 目录 局部搜索算法 简单局部搜索 迭代局部搜索 01 局部搜索算法 1.1 什么是局部搜 ...

  4. WLAN(Wireless Local Area Network)——无线局域网

    目录 一.WLAN基础 1.分类 2.各种无线网络技术应用 3.WLAN的定义 4.WLAN技术标准 (1)802.11 (2)802.11b (3)802.11a (4)802.11g (5)802 ...

  5. 随想录(thread类的编写)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 曾经有一段时间我不是很清楚在c++下面,为什么创建一个thread只需要继承一下.然后重写一下r ...

  6. Java内存区域(运行时数据区域)和内存模型(JMM)

    原文作者:czwbig 原文:https://www.cnblogs.com/czwbig/p/11127124.html Java 内存区域和内存模型是不一样的东西,内存区域是指 Jvm 运行时将数 ...

  7. 读书笔记——深入理解JVM(JVM自动内存管理)

    简介 本系列为<深入理解Java虚拟机-JVM高级特性与最佳实践>一书的阅读笔记. 本书开头介绍了JVM发展的历史,接着介绍了JVM是如何实现自动内存管理的. 本章节主要介绍: JVM的存 ...

  8. 精华推荐 | 【JVM深层系列】「GC底层调优系列」一文带你彻底加强夯实底层原理之GC垃圾回收技术的分析指南(GC原理透析)

    前提介绍 很多小伙伴,都跟我反馈,说自己总是对JVM这一块的学习和认识不够扎实也不够成熟,因为JVM的一些特性以及运作机制总是混淆以及不确定,导致面试和工作实战中出现了很多的纰漏和短板,解决广大小伙伴 ...

  9. WCF后续之旅(11): 关于并发、回调的线程关联性(Thread Affinity)

    对于一般的多线程操作,比如异步地进行基于文件系统的IO操作:异步地调用Web Service:或者是异步地进行数据库访问等等,是和具体的线程无关的.也就是说,对于这些操作,任意创建一个新的线程来执行都 ...

最新文章

  1. ***网站必备:(经典语句)
  2. Windows批量添加防火墙例外端口
  3. 2018危机与机遇丨PMCAFF年度精选合集
  4. RESTful Web服务可发现性,第4部分
  5. python如何输出两列数据_如何用python将一列数据分为两列?
  6. java-成员变量的属性与成员函数的覆盖
  7. matlab 传递函数 画出频率响应,MATLAB环境下频率响应曲线的绘制方法
  8. MATLAB_R2018b安装教程
  9. 触动精灵 获取getColor颜色失败
  10. java 一元二次方程_java求解一元二次方程
  11. java合成wav在linux出错,Java audio fails to play wav file in Linux
  12. 易大师接口自动化测试平台如何创建不同协议的接口并进行测试
  13. 数据库MySQL(基础六)
  14. openwrt mesh网络设置
  15. 第十二届蓝桥杯 2021年省赛真题 (Java 大学A组) 第一场
  16. 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005
  17. new FileReader()
  18. Python - 文本处理模块
  19. Windows server 2019 - 磁盘加密(BitLocker)
  20. PIPI OJ 1334: PIPI计数(unordered_map的应用)

热门文章

  1. Linux Mint TLP设置
  2. 【U8+】用友U8+登录账套,提示“指定的参数已超出有效值的范围。参数名:index”
  3. 洛谷P1010 [NOIP1998 普及组] 幂次方题解
  4. 微信登录流程图(转)
  5. 将标签转为onehot编码
  6. 职业也如学习一样,逆水行舟不进则退
  7. 90 后的他带出7 个“师弟”,爱说话的程序员脱单更快?
  8. java微信小程序调用支付接口
  9. 交换机loopback口
  10. C++入门——神奇的引用