对象创建过程时序图,对象创建过程 简述对象创建过程
概述通常,我们只需要使用new关键字来创建一个对象。对于java虚拟机来说,需要经历一系列的过程。首先我们要搞清楚对应的是哪个类,这个类有没有加载过。如果还没有加载,我们需要先加载,然后给要创建的对象分配内存,再初始化对象,才能使用完整的对象。
寻找类当java虚拟机遇到一条字节码新指令时,它首先根据指令的参数在常量池中定位一个类的符号引用,并检查这个符号引用所代表的类是否已经被加载、解析和初始化。如果没有,它需要先执行类加载过程(这里暂时不展开)。
分配内存在一系列寻找类的操作之后,java虚拟机就知道要创建哪个类的对象了。此时,它需要内存来放置要创建的对象。所以下一步是分配内存。加载一个类后,对象所需的内存就确定了。现在需要找到一个空闲区域来划分要生成的对象。
分配模式指针冲突模式
这个方法需要把使用过的内存放在一边,不用的放在另一边,指针指向第一个空闲的位置。此时分配内存只需要将指针移动对象大小到空闲位置即可。但是我们知道,内存是分配回收的,连续分配回收之后,内存就不连续了。如果用这种方法,显然是不行的,所以我们需要使用的垃圾处理器是有空间压缩合并功能的,比如Serial和ParNew。
空闲列表模式
还有一种方式,自由列表方式。顾名思义,我们都知道列表是用来记录所有空闲块的。这需要维护一个单独的列表。基于清算算法的收集器CMS就是采用了这种方法。不过已经做了进一步的优化。为了在大多数情况下使分配更快,设计了分配缓冲器。从空闲列表中取出一个更大的内存,然后使用指针冲突在这个内存中分配它。
并发问题对象的创建是虚拟机中非常频繁的行为。即使使用最简单的指针碰撞方法,只修改指针指向的位置,在并发的情况下也不是线程安全的(如果内存正在分配给对象A,指针位置没有修改,对象B需要分配内存,相当于使用了错误的指针位置)。
同步处理
一种处理方式是同步处理。实际上,虚拟机采用CAS失败重试来保证更新操作的原子性。当对象A正在分配内存时,它表明它正在被分配。当对象B到达时,发现它正在被分配,因此分配失败。再试一次,请求分配,直到对象A被分配,对象B继续分配。
空间隔离
另一种方式是根据线程将内存分配划分到不同的空间,即预先给每个线程分配一小块内存,称为线程本地分配缓冲区TLAB。当一个线程需要分配内存的时候,它现在就在自己的本地缓冲区分配,不够的话就同步锁定。虚拟机是否使用TLAB可以通过-XX: /-useTLAB参数设置。
在通过初始化将空间分配给对象之后,我们需要初始化对象。初始化对象有三个步骤。
预初始化将除对象头以外的所有内存空间初始化为零(如果使用了TLAB,此步骤可以在TLAB分配之前完成)。这一步确保了对象的实例字段可以直接在java代码中使用,而无需赋值。
设置对象标题。由于对象头位于最前面,所以应该会存储一些关于对象的基本信息,包括对象是哪个类的实例,如何找到类的元信息,对象的hash码(其实这里并没有设置,而是在调用Object:hashCode()时计算),对象的GC生成年龄,锁等信息。此时,已经在虚拟机级别创建了一个新对象。
初始化的最后一步是构造其他资源(父类等。)和对象所需的状态信息,从而构建出真正可用的对象。
创建一个对象的过程很简单,就是找基础(类),放在哪里(分配内存),初始化(设置我们想要的)。
版权归作者所有:原创作品来自博主小二上九8,转载请联系作者取得转载授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。