转载

3.对象的创建过程解析

3.对象的创建过程解析

其中类加载机制如下:

3.对象的创建过程解析

对象创建过程解析:

1、类加载检查

类在加载过程中会首先判断该类是否已被加载,即,在方法区(元空间)上的常量池中去查找指向该类的指令,如果存在,再去判断该指令指向的类是否已经被加载、解析、初始化过,如果没有,就加载此类。

2、分配内存

当类被加载完之后,虚拟机就会给对象分配内存,此时对象的大小已经确定,虚拟机会从堆(栈)的内存区域中划分出该对象大小空间的区域供存放该对象。

1、指针碰撞:

指针碰撞时jvm虚拟机默认的给对象分配内存的方式,即:把堆(或栈)上的一部分内存分成两部分,一部分依次放满了对象,此时对象在这部分内存上是整齐排放着,另一部分是空白内存区域,等待放对象。两块区域的间隔点是用一个指针进行标记,如果在这块内存中又创建了对象,则指针会向后移动这个对象的大小的地址,供这个对象存放。

3.对象的创建过程解析

2、空闲列表:

当内存上存放的对象不是整齐规整存放的话,就会出现许多空白区域与对象交叉出现,此时就不能使用指针碰撞的方式去分配内存,空闲列表的方式就是维护一个可以存放对象的内存地址的集合列表,即记录哪些内存区域是可以存放对象的,当创建对象时,在列表中找一个空间合适的一块区域去存放,然后再更新列表。

3.对象的创建过程解析

在以上分配内存的过程中,如果在给对象a分配内存的同时指针还没来得及修改,对象b同时也使用了原来的这个指针来分配内存。就会出现一块内存分配给了两个对象,即并发问题。

解决并发问题的方式:

1、CAS

CAS即Compare and Swap,比较并交换算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。这里进行简述:利用cas方式解决创建对象的并发问题的逻辑是:对象在进行分配内存之前会将该线程期望的指针值与内存上的原有的指针值进行比较,如果相同,则先修改内存上的指针值,即向后移动该对象大小的空间,然后存放对象。如果不相同,则返回现在的指针值,然后重试以上操作。

2、本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)

把将要存放对象的空白内存区域分成若干小块,每个线程只允许在自己的那一小块的内存上进行分配对象内存区域。

3、初始化

即给对象赋默认值。如果不赋默认值,这个对象的该字段如果不set值的话,就无法get该字段的内容,程序会出错。如果赋默认值之后,就可以返回默认值。

4、设置对象头

对象由对象头(Header)、 实例数据(Instance Data)和对齐填充(Padding)三部分组成。

对象头:包含了该对象的必要信息,不仅包括该对象的一些类元信息地址指针,还包含其他信息,比如对象的分代年龄,锁信息等。

实例数据:对象中各个实例字段的数据。

对齐填充:其中为了保持对象内存的整齐性,还包括了对齐指针来进行对对象的内存大小的填充。

5、执行init()方法

为对象赋用户自己的值,执行构造方法。

对象头的类元信息解析

3.对象的创建过程解析

如上图所示:

对象在堆中创建,其对象头中存在指向该对象的类元信息的指针,也就是说,如果对象想要找到该对象的成员方法的具体方法内容(代码),就是通过这个对象头内的指针找的。

duixiang.add();

区分对象、类对象、类元信息:

类对象:类加载完成之后,是java虚拟机为方便用户操作该类的类元信息而创建的镜像对象,里面没有该类的信息,但是通过该类对象可以访问该类的信息。存放在堆中。

class<?extends Duixiang> duixiangClass = duixiang.getClass();

类元信息:存放类的相关信息,比如变量与成员方法,在方法区中。

对象头中的指针为压缩指针,作用是节省内存空间

未完待续~~~~

原文  https://segmentfault.com/a/1190000023287744
正文到此结束
Loading...