逃逸、TLAB、对象分配顺序、对象内存布局
2019-04-16 14:55
134 查看
逃逸:
当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他过程或者线程所引用,这种现象称作指针(或者引用)的逃逸
逃逸状态:
- GlobalEscape(全局逃逸), 即一个对象的引用逃出了方法或者线程。例如,一个对象的引用是复制给了一个类变量,或者存储在在一个已经逃逸的对象当中,或者这个对象的引用作为方法的返回值返回给了调用方法。
- ArgEscape(参数级逃逸),即在方法调用过程当中传递对象的应用给一个方法。这种状态可以通过分析被调方法的二进制代码确定。
- NoEscape(没有逃逸),一个可以进行标量替换的对象。可以不将这种对象分配在传统的堆上
逃逸影响:
- 堆分配对象变成栈分配对象。一个方法当中的对象,对象的引用没有发生逃逸,那么这个方法可能会被分配在栈内存上而非常见的堆内存上。
- 消除同步。线程同步的代价是相当高的,同步的后果是降低并发性和性能。逃逸分析可以判断出某个对象是否始终只被一个线程访问,如果只被一个线程访问,那么对该对象的同步操作就可以转化成没有同步保护的操作,这样就能大大提高并发程度和性能。
- 矢量替代。逃逸分析方法如果发现对象的内存存储结构不需要连续进行的话,就可以将对象的部分甚至全部都保存在CPU寄存器内,这样能大大提高访问速度
创建对象与指针碰撞:
虚拟机维护堆区的空间,哪些被被使用,哪些是未使用,在多个线程同时创建,维护指针的使用情况会有并发问题,发生指针碰撞。解决问题有CAS锁机制、线程分配缓冲区(TLAB)。
线程分配缓冲区(TLAB):
哪个线程需要分配内存,就在哪个线程的TLAB上分配空间,可以使用-XX:+/-UseTLAB参数来设定(thread.start()调用时,分配TLAB空间)。缺省情况下仅占有整个Eden空间的1%,也可以通过选项-XX:TLABWasteTargetPercent设置TLAB空间所占用Eden空间的百分比大小。
TLAB只是让每个线程有私有的分配指针,但底下存对象的内存空间还是给所有线程访问的,只是其它线程无法在这个区域分配而已。
对象分配顺序:
对象内存布局:
对象头:Mark Word 部分数据的长度在32位和64位虚拟机(未开启压缩指针)中分别为32bit和64bit,存储对象自身的运行时数据如哈希值等。Mark Word一般被设计为非固定的数据结构,以便存储更多的数据信息和复用自己的存储空间。类型指针指向它的类元数据的指针,用于判断对象属于哪个类的实例。
实例数据:存储的是真正有效数据,如各种字段内容,各字段的分配策略为相同宽度的字段总是被分配到一起,便于之后取数据。父类定义的变量会出现在子类定义的变量的前面。
对齐填充部分:仅仅起到占位符的作用,对象的大小为8字节的倍数。
相关文章推荐
- Java中的逃逸分析和TLAB以及Java对象分配
- Hotspot虚拟机--对象分配,内存布局,访问定位
- Java中的逃逸分析和TLAB以及Java对象分配
- 对于结构体对象在内存中分配地址的顺序及其占内存大小的疑问
- Java中的逃逸分析和TLAB以及Java对象分配
- java虚拟机在java堆中对象内存分配、布局、访问
- C++对象模型之简述C++对象的内存布局
- c++对象内存的分配
- Java虚拟机堆内存中对象的分配、布局、访问 -----以HotSpot虚拟机为例
- C++ 对象的内存布局(上)
- PHP对象在内存中的分配
- JVM对象的内存布局和访问
- 对象内存布局 (8)
- 对象内存布局 (10)
- 对象内存布局 (11)
- (转帖)C++ 对象的内存布局----主要看virtual 继承的解释
- 对象内存布局系列博文写后记
- 探讨C++ 变量生命周期、栈分配方式、类内存布局、Debug和Release程序的区别
- PHP对象在内存堆栈中的分配
- 深入理解C++对象模型-对象的内存布局,vptr,vtable