> 文档中心 > java创建对象全过程

java创建对象全过程

java是一门面向对象的编程语言,在程序运行过程中无时无刻都有对象被创建。在语言层面上,创建对象通常(例外:复制、反序列化)仅仅是一个new关键字而已,而在虚拟机中对象的创建又是怎样的一个过程呢?

1.检查
当Java虚拟机遇到一条字节码new指令时,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

2.分配内存
在类加载检查通过后,将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的过程相对于把一块确定大小的内存从java堆中划分出来。那么按照内存是否规整分为两种方式:指针碰撞、空闲列表。

指针碰撞(Bump the Pointer):内存是规整的,所有被使用过的内存和未被使用的空闲的内存各在一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间方向移动一段与对象大小相等的距离。

空闲列表(Free List):内存不是规整的,已使用的内存和空闲的内存交错,那么虚拟机就需要维护一个记录着那些内存块是可用的一个列表,分配内存的过程就是在列表中找到一块足够大的空间划分给该对象实例,并更新列表上的记录。

分配空间时的并发问题解决:因为创建对象在虚拟机中非常频繁,在并发操作的情况下会出现线程安全问题(正在在给对象A分配内存,指针还没来得及修改,此时对象B又同时使用了原来的指针分配内存的情况)。解决方案有两种:一种是对分配内存空间的动作进行同步处理(采用CAS配上失败重试的方式保证更新操作的原子性),把内存分配按不同线程划分在不同空间进行,即预先为每个线程在java堆中分配一小块内存,称为本地线程分配缓冲,哪个线程要分配内存,就在哪个线程的本地缓冲区分配,值用本地缓冲区用完了,分配新的缓存区时才需要同步锁定。虚拟机是否使用TLAB,可通过-XX:+/-UseTLAB参数来设定。

TLAB(ThreadLocalAllocBuffer):是一个本地线程分配缓冲区,是线程的一块私有内存,如果设置了虚拟机参数 -XX:UseTLAB,在线程初始化时,同时也会申请一块指定大小的内存,只给当前线程使用,这样每个线程都单独拥有一个Buffer,如果需要分配内存,就在自己的Buffer上分配,这样就不存在竞争的情况,可以大大提升分配效率,当Buffer容量不够的时候,再重新从Eden区域申请一块继续使用,这个申请动作还是需要原子操作的。

3.初始化
虚拟机将分配到的内存空间都初始化为零值,如果使用了TLAB,这步也可以提至TLAB分配时进行。此过程保证了对象的实例字段不设置初始值也可以正常使用。

4、设置参数
对象属于哪个类的实例、如何找到类的元数据信息、对象的哈希码、对象的GC分代年龄、是否使用偏向锁等等。

5、构造函数
执行自定义的(或是自动生成的)构造函数方法进行对象按照程序员的意愿初始化。