HotSpot对象的创建及内存布局

1.1对象创建过程

  1.首先检查这个指令的参数是否能在运行常量池中找到一个类的符号引用。若常量池中没有该类的符号引用,则说明该类没有被定义,抛出异常。

  2.检查这个符号代表的类是否已被加载、解析、初始化过。若没有,则先执行相应的类加载过程。

  3.虚拟机为新生对象分配内存。(对象所需内存大小在类被加载完成后便可完全确定,选择哪种分配方式由java堆是否规整决定。Java堆是否规整由所采用的垃圾收集器是否带有压缩整理的功能决定。)

    指针碰撞(Serial、ParNew等带Compact过程的收集器)

     假设Java内存是完全规整的,所有用过的内存放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点指示器,那所分配内存就是把指针向空闲空间那边移动一段与对象大小相等的距离。

    空闲列表(使用CMS基于Mark-Sweep算法的收集器)

     如果Java堆中的内存并不规整,已使用的内存和空闲的内存相互交错,虚拟机就必须维护一个列表,记录那些内存块可用,在分配的时候在列表上找到一块足够大的空间划分给对象实例,并更新列表记录。 

  4.初始化内存空间为零值。

  5.设置对象头中的信息。

  6.调用对象构造函数进行初始化。

  此时对象创建完成。

1.2内存分配的并发问题解决

  对象创建在虚拟机中属于频繁操作,这就涉及到了并发操作(当给对象A分配内存并且还没有分配完毕时,给对象B分配相同的的内存区域)。解决方案主要包括两种:算法和TLAB

  1. CAS算法 

    通过CAS算法来对进行内存分配,若失败,则重新分配

  3.2 TLAB 本地线程分配缓冲(Thread Local Allocation Buffer, TLAB)

    将所有内存分配的操作划分到多个不同线程中进行,预先给每个线程分配一小块内存,称为TLAB。哪个线程需要分配内存,就在那一个线程的TLAB上进行分配。只有当线程的TLAB用完了,在分配新的TLAB的时候,才需要进行同步锁定。是否使用TLAB通过-XX:+/-UseTLAB参数设置。java层面与之对应的是ThreadLocal类的实现。

2.1对象内存布局

  

原文地址:https://www.cnblogs.com/zhaosong-0102/p/12171581.html