您的位置:首页 > 其它

逃逸、TLAB、对象分配顺序、对象内存布局

2019-04-16 14:55 134 查看

逃逸:

       当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他过程或者线程所引用,这种现象称作指针(或者引用)的逃逸

逃逸状态:

  1. GlobalEscape(全局逃逸), 即一个对象的引用逃出了方法或者线程。例如,一个对象的引用是复制给了一个类变量,或者存储在在一个已经逃逸的对象当中,或者这个对象的引用作为方法的返回值返回给了调用方法。
  2. ArgEscape(参数级逃逸),即在方法调用过程当中传递对象的应用给一个方法。这种状态可以通过分析被调方法的二进制代码确定。
  3. NoEscape(没有逃逸),一个可以进行标量替换的对象。可以不将这种对象分配在传统的堆上

逃逸影响: 

  1. 堆分配对象变成栈分配对象。一个方法当中的对象,对象的引用没有发生逃逸,那么这个方法可能会被分配在栈内存上而非常见的堆内存上。
  2. 消除同步。线程同步的代价是相当高的,同步的后果是降低并发性和性能。逃逸分析可以判断出某个对象是否始终只被一个线程访问,如果只被一个线程访问,那么对该对象的同步操作就可以转化成没有同步保护的操作,这样就能大大提高并发程度和性能。
  3. 矢量替代。逃逸分析方法如果发现对象的内存存储结构不需要连续进行的话,就可以将对象的部分甚至全部都保存在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字节的倍数。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: