Java对象创建

创建的步骤

1 检查 对象类是否已经加载

    虚拟机 遇到new指令时,检查 对象类是否已经加载,解析,初始化过,没有则执行类加载过程。

2 分配内存

    类加载,检查通过后,开始为对象分配内存,

        内存大小,在类加载后就已经确定了,

    从Java堆中将内存划分出来,有两种方式

        1 指针碰撞。Java堆内存是规整的,已用内存,可用内存是分开的,用一个指针作为分界点。分配内存就是将分界指针向可用内存方移动,指定大小内存,将该内存划分给对象。

        2 空闲列表,Java堆内存是不规整的,已用内存和可用内存是交错的,虚拟机需要维护一个列表来记录那些可用,那些不可用。这样就需要从列表中找到一块足够大的内存,来划分给对象。

      由于对象的创建是非常频繁的,分配内存需要考虑线程安全。解决这一问题有两种方式。

         1 线程同步,对分配内存空间的动作进行同步处理,虚拟机采用CAS配失败重试方式保证更新操作原子性。

        2  线程内存独立。每个线程在Java堆中预先分配一块内存,称为本地线程分配缓冲,(Thread Local Allocation Buffer TLAB),线程中的对象创建就使用该线程的TLAB,TLAB用完,需要划分新的TLAB空间是,还是需要线程同步。虚拟机是否使用TLAB 可以设参数来指定-XX:+/-UseTLAB

3 对象初始化

虚拟机首先将要分配到的内存空间都初始化为零值(不包括对象头),

** 对象的初始化也分为两个部分**

1 实例数据部分的初始化。对象的实例字段初始化为,字段类型所对应的零值,Numbic 对应为0,所有的对象为null,boolean类型为false;

2 对象头的初始化,对象头信息设置,例如这个对象是哪个类的实例,如何查找到类的元数据,对象HashCode,对象的GC分代年龄,等

4 调用<init>

** 其实经过以上三步,对于虚拟机而言,对象已经创建完毕,对于我们程序员而言,对象创建还刚刚开始。**

执行init方法,将所有的字段,按照我们程序员的意愿进行初始化,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class  Test{

    static int a=3;

    static

    {

        b=4;

    } 

    static b=2;

    public static main(String \[\]args)

    {

        System.out.prinln(\"a:\"+a+\",\"+\"b:\"+b);

    }
}

对于Test这个类,经过3步后,a字段的值 为0,b为0,经过第四步后,a字段的值为 3, b先为4 然后为2

在main中输出的结果是 a:3,b2