HotSpot虚拟机对象探秘++对象的创建

171 阅读2分钟

想进一步了解虚拟机内存中的其他细节,譬如它们是如何创建、如何布局以及如何访问的。 对于这些涉及细节的问题,必须把讨论范围限定在具体的虚拟机和集中在某一个内存区域才有意义。

对象的创建

  1. 语言层面、虚拟机层面
  2. 什么对象(普通的对象、数组对象、Class对象) 这里讨论的对象限于普通的对象

new的背后 当Java虚拟机遇到一条字节码 new 指令时,

  1. 首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用, 并且检查这个符号引用代表的类是否已被加载、解析、初始化过。 如果没有,先加载。
  2. 在类加载检查完成后,接下来虚拟机将为新生对象分配内存
内存分配方式:指针碰撞,空闲列表。选择哪种分配方由Java堆是否规整决定
还有个需要考虑的问题:对象创建在虚拟机中是非常频繁的行为,即使仅仅修改一个指针(内存分界点的指示器)所指向的位置,在并发情况下也并不是线程安全的,可能出现正在给对象A分配内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况。
解决这个问题有两种可选方案:
一种是对分配内存空间动作进行同步处理--实际上虚拟机是采用CAS配上失败重试方式保证更新操作的原子性。
另外一种是把分配内存的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer)TLAB,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。
  1. 内存分配完成后,虚拟机必须将分配到的内存空间(但不包括对象头)都初始化为零值
  2. 接下来,Java虚拟机还要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码,对象的GC分代年龄等信息。这些信息存放在对象的对象头之中。
  3. 至此,从虚拟机的视角来看,一个新的对象已经产生了。但是从Java程序的视角看来,对象创建才刚刚开始——构建函数还没执行,接下来按照程序员的意愿对对象进行初始化。