Object obj = new Object();在这个过程中JVM都做了哪些工作呢?
1.JVM首先检测类是否被加载 即:检查常量池中是否存在该类的符号引用,如果没有先加载该类。
2.类加载后,先为该对象分配内存空间
分配内存空间过程中需要考虑的问题:
2.1 :内存空间是否规整
2.1.1:假设Java堆中内存是连续规整的,也就是说Heap中一侧是已经使用过的空间,另一侧是空闲空间。则此时使用指针指向起始空间内存,当需要分配新空间时,
只需要将指针向后移动到指定的空间大小即完成空间内存的分配,这种分配方式称为“指针碰撞”Bump the Pointer
2.1.2:假设内存不是连续规整的,空闲空间和已经使用的空间是相互交错的,此时JVM就需要记录哪些空间已经被占用,哪些是可用的,分配时采用相对比较大的空间
给实例,然后更新空间内存记录,这种方式称为“空闲列表”。Free List
而实际分配空间时是采用哪种方式的是由JVM的堆是否规整决定的, 而堆是否规整是由所采用的垃圾收集器是否带有亚索整理的功能决定的。如果JVM使用Serial,ParNew 等带有
compact过程的收集器时则采用指针碰撞的内存分配方式;而如果使用CMS这种给予Mark Sweep 算法收集器时,采用空闲列表的方式。
2.2:对象的创建过程十分复杂,如何解决并发带来的不安全问题
方法一:同步,即对分配内存空间的动作进行同步处理-采用CAS加上失败重试的方式保证更新操作的原子性。
方法二:TLAB,把内存分配的动作按照线程划分在不同的空间上进行。每个线程预先分配一小块内存,这种方式称为本地线程分配缓冲,这种方式只需在分配新的TLAB进行同步
锁定是否采用TLAB方式通过使用-Xx:+/-UserTLAB决定
3.内存空间分配完成后,要进行一些必要的初始化工作
初始化工作包含哪些,
3.1 该实例为哪一个类的实例
3.2 类的元数据信息
3.3 对象的哈希码
3.4 对象的GC分代信息
这些信息位于对象的头信息中,初次之外,对象的其他字段都还是0,对象创建完成,但还没有进行初始化工作。
4.对象的初始化执行init方法
一个Java对象就创建完成了。