jvm-对象的创建过程

在java中使用new创建对象时,虚拟机创建的过程:

new MyObject();

1、虚拟机会检查MyObject这个类是否存在,有没有被加载。如果MyObject没有被加载过,那么就先加载这个类;

2、虚拟机根据MyObject类的类信息在堆中分配内存空间,分配内存有两种方式:

(1)指针碰撞:当内存是规整的,此时有一个指针,在该指针一侧的内存是已经被分配了,而另一侧的内存则是空闲的,当创建对象要分配内存时,指针向空闲内存的一侧移动与要创建的对象大小相等的距离,这段距离之间的内存就用于存放要创建的对象。

(2)空闲列表:内存很少会是规整的,大多都是东一块西一块的的破碎内存,此时使用一个列表把空闲的内存记录下来,当要创建对象时,找出最合适的一块空闲内存用于存储这个要创建的对象。

以上两种方法在单线程中是没有问题的,但是,当处于多线程的时候,“指针碰撞”方式,在一个线程中创建第一个对象,读取了指针的地址,正要把指针向空闲内存一侧移动时,第二个线程也要创建第二个对象,此时指针还没有被修改,所以在第二个线程中读取的指针还是原来的地址,然后分配内存也是从那个地址把指针向空闲的一侧移动等于第二个对象大小的距离。。。这个时候,第一个线程创建的第一个对象,与第二个线程创建的第二个对象 会相互覆盖,数据就会出错。

而解决方法有两个:

(1)创建对象的时候进行同步操作,这样就不会出现多个线程读取到的指针是相同的情况了。。但是,同步会导致效率低下。

(2)使用TLAB本地线程分配缓冲,也就是每个线程在创建时都先分配一块堆内存用作缓冲,在哪个线程创建的对象都在这个线程所属的TLAB中创建对象。

3、分配完对象的内存空间后,把这块内存的值置为零置,这样的话,对象中没有被初始化的实例字段就存在初始值了,对象变量字段初始值为null,基本类型为对应的零值。。

4、初始化对象头数据,对象头数据有 运行时数据和类型指针,

    对象头运行时数据:GC年龄分代、锁状态标志、线程持有的锁、hashcode哈希码等。

    类型指针:指向方法区中类型信息的指针。类型信息就是编译后的代码以及其他关于这个类的数据信息。

5、调用构造方法进行初始化。

猜你喜欢

转载自blog.csdn.net/qq_36951116/article/details/83275616