聊聊JVM Young Gen(年轻代)Eden区的线程本地分配缓冲区-TLAB(Thread Local Allocation Buffer)

Posted Dreamer who

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊聊JVM Young Gen(年轻代)Eden区的线程本地分配缓冲区-TLAB(Thread Local Allocation Buffer)相关的知识,希望对你有一定的参考价值。

JVM一般采用分代来管理堆内存,如下图:

                                                

逻辑上是连续的,但不同的gc回收算法在实际分配内存时不一定是连续的。

一般大部分对象都在年轻代中的Eden区创建,除个别大对象直接在老年代分配。因为堆是共享的,多个线程可以同时创建对象,为了保证线程安全,Eden区又被分配成一个个线程本地分配缓冲区-TLAB(Thread Local Allocation Buffer)(不排除个别jvm没采用),这个TLAB是线程私有的,每个线程都有自己的TLAB,避免了多线程环境下使用同步技术带来的性能损耗

 

当在TLAB因为空间不够,无法分配对象时,根据JVM的相关配置会发生两种情况:

(1)当前线程获取一个新的TLAB

(2)对象被分配在TLAB外,即分配在Eden的共享区,如上图的common area所示区域。

 

当情况(1)发生时,当前线程的TLAB就“退休了”,对象会分配在新的TLAB。当情况(2)发生时,对象会分配在Eden的共享区,此时需用同步手段保证安全性,所有这种情况下就不可避免的产生了一些性能问题。当TLAB和Eden的共享区都没有空间的时候,年轻代gc回收算法被触发。当年轻代gc回收算法触发后释放的空间还不够的时候,对象会被直接在老年代创建。

 

和TLAB相关的JVM参数:

 

  • -XX:AllocatePrefetchStyle=style

Sets the generated code style for prefetch instructions. The style argument is an integer from 0 to 3:

0

Don’t generate prefetch instructions.

1

Execute prefetch instructions after each allocation. This is the default parameter.

2

Use the thread-local allocation block (TLAB) watermark pointer to determine when prefetch instructions are executed.

3

Use BIS instruction on SPARC for allocation prefetch.

Only the Java HotSpot Server VM supports this option.

 

  • -XX:+UseTLAB

Enables the use of thread-local allocation blocks (TLABs) in the young generation space. This option is enabled by default. To disable the use of TLABs, specify the option -XX:-UseTLAB.

 

  • -XX:TLABSize=size

Sets the initial size (in bytes) of a thread-local allocation buffer (TLAB). Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, or g or G to indicate gigabytes. If this option is set to 0, then the JVM selects the initial size automatically.

jvm默认为0

 

  • -XX:+PrintTLAB - TLAB summary in GC log - diagnostic. ENABLE!

 

  • -XX:ResizeTLAB - Eables resizing of TLABs,默认启用

 

  • -XX:MinTLABSize

 

默认ResizeTLAB是启用的,新的TLAB的大小由三个因素决定:应用的线程数量、内存分配率、Eden大小。

对源码感兴趣的可以参考:
https://github.com/openjdk/jdk/blob/jdk8-b120/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp
https://github.com/openjdk/jdk11u/blob/master/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp

 

参考:

http://geekswithblogs.net/JoshReuben/archive/2016/04/11/jvm-tuning.aspx
https://plumbr.io/handbook/garbage-collection-in-java
https://dzone.com/articles/jrockit-gc-action
https://blog.pythian.com/understanding-java-virtual-machinejvm-architecture-part1/
https://docs.oracle.com/en/java/javase/13/docs/specs/man/java.html#standard-options-for-java

https://alidg.me/blog/2019/6/21/tlab-jvm
https://umumble.com/blogs/java/how-does-jvm-allocate-objects%3F/

http://performantcode.com/2019/03/03/thread-local-allocation-buffers/

以上是关于聊聊JVM Young Gen(年轻代)Eden区的线程本地分配缓冲区-TLAB(Thread Local Allocation Buffer)的主要内容,如果未能解决你的问题,请参考以下文章

jvm中的新生代Eden和survivor区

JVM年轻代年老代永久代

jvm的内存模型

JVM垃圾回收--年轻代年老点和持久代

JVM总结

[转]JVM内存区域划分Eden SpaceSurvivor SpaceTenured Gen,Perm Gen解释