对象的创建过程

来源:互联网 发布:小果软件手机 编辑:程序博客网 时间:2024/05/24 05:11
       虚拟机遇到一条new指令时,首先去常量池中寻找有没有这个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有则会先执行相应的类加载过程,在通过检查后,虚拟机为该新生对象分配内存。

       对象所需内存的大小在类加载完成后便能完全确定,简单来说为对象分配空间就是把一块确定大小的内存从Java堆中划分出来。至于如何划分空间,暂不深入讨论,但是需要引起注意的是多线程频繁地在同一块Java堆中分配内存时面临的并发问题。
       解决这个问题有两种方案,一种是对分配内存空间的操作进行同步处理 ,虚拟机采用的CAS和失败重试的方式保证操作的原子性;另一种是把内存分配的动作按照线程划分在不同的空间进行,即每个线程都在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,简称TLAB)。线程要分配内存时,先在自己私有的TLAB上分配,只有TLAB用完并分配新的TLAB时需要同步锁定操作。虚拟机设置是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定。

       对象的内存分配完之后,虚拟机需要将这块内存空间都初始化为零值(除了对象头),如果使用了TLAB ,这一工作也可以提前至TLAB分配时进行。内存空间虽然为零,但是对应java代码就是各类型的初始状态。例如int类型的初始化状态为0,布尔类型的初始化状态为false。也是为什么对象刚创建就可以使用的原因。

       之后,虚拟机要对对象进行必要的设置,例如该对象是哪个类的实例、如何才能找到类的元数据信息(即类信息)、对象的哈希吗、对象的GC分代年龄等信息。这些信息都将会存放在对象头(Object Header)之中。

        上述的工作从虚拟机角度来说,一个新的对象已经产生,但从Java程序的视角来看,对象创建才刚刚开始—<init>方法还没有执行,所有的字段都还是为零。所以,一般来说(由字节码中是否跟随invokespecial指令所决定),执行new指令之后会接着执行<init>方法,将对象进行初始化。

0 0
原创粉丝点击