1.加载类:当执行new语句时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过,如果没有,那必须先执行相应类的加载过程。
2.分配内存(每个对象占用的内存都是连续的):对象所需内存大小在类加载完成后便可完全确定。根据Java堆中的内存是否规整(用过的内存都放在一边,空闲的内存放在另一边),分两种分配方式:
指针碰撞(Bump the Pointer):在空闲区域和已使用区域之间放一个指针,分配内存仅
仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离。空闲列表(Free List):虚拟机维护一个列表,记录哪些内存块是可用的
Java堆是否规整由所采用的垃圾收集器是否带有压缩整理功能决定。
在分配内存空间时,如何解决对象A和对象B同时使用原来的指针分配内存?
解决这个问题有两种方案:
1)对分配内存空间的动作进行同步处理——实际上虚拟机采用的CAS配上失败重试的方式保证更新操作的原子性。
2)把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(TLAB)。只有TLAB用完并分配新的TLAB时,才需要同步锁定。虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定
3.初始化:将分配到的内存空间初始化为零值(不包括对象头),这里可以为字段赋予默认值。
4.设置对象头:记录对象是哪个类的实例、如果找到类的元数据类型、对象的哈希吗、对象的GC分代年龄等信息