Jvm(16),jvm创建对象---对象在内存中的创建

1、对象的创建

  java是面向对象的语言,因此对象的创建无时无刻都存在。在语言层面,使用new关键字即可创建出一个对象。但是在虚拟机中,对象创建的创建过程则是比较复杂的。

  首先,虚拟机运到new指令时,会去常量池检查是否存在new指令中包含的参数,比如new People(),则虚拟机首先会去常量池中检查是否有People这个类的符号引用,并且检查这个类是否已经被加载了,如果没有则会执行类加载过程。

  在类加载检查过后,接下来为对象分配内存当然是在java堆中分配,并且对象所需要分配的多大内存在类加载过程中就已经确定了。为对象分配内存的方式

根据java堆是否规整分为两个方法:而java堆是否带有压缩整理功能有关。

1、指针碰撞(Bump the Pointer),

指针碰撞:如果java堆是规整的,即所有用过的内存放在一边,没有用过的内存放在另外一边,并且有一个指针指向分界点,在需要为新生对象分配内存的时候,只需要移动指针画出一块内存分配和新生对象即可;指针碰撞:如果java堆是规整的,即所有用过的内存放在一边,没有用过的内存放在另外一边,并且有一个指针指向分界点,在需要为新生对象分配内存的时候,只需要移动指针画出一块内存分配和新生对象即可;我们来看下面的图片就是说左边的都是没有用过的,右边的都是已经用过的内从这个时候假如有新的对象被new出来了之后,在堆空间中就会把中间的那条线往左移动。指针碰撞是有规则的,规整的。

2、空闲列表(Free List)。

空闲列表:当java堆不是规整的,意思就是使用的内存和空闲内存交错在一起,这时候需要一张列表来记录哪些内存可使用,在需要为新生对象分配内存的时候,在这个列表中寻找一块大小合适的内存分配给它即可。而java堆是否规整和垃圾收集器是否带有压缩整理功能有关。

二,线程安全

  在为新生对象分配内存的时候,同时还需要考虑线程安全问题。因为在并发的情况下内存分配并不是线程安全的。有两种方案解决这个线程安全问题,

1、为分配内存空间的动作进行同步处理;

相当于加一把锁,缺点,效率低下

2、为每个线程预先分配一小块内存,

称为本地线程分配缓存(Thread Local Allocation Buffer, TLAB),哪个线程需要分配内存,就在哪个线程的TLAB上分配。

相当于为每个线程分配一块内存区域,互不干扰,假如线程满了之后,会采用线程同步的策略,重新分配一块区域的。

三,初始化

  内存分配后,虚拟机需要将每个对象分配到的内存初始化为0值(不包括对象头),这也就是为什么实例字段可以不用初始化,直接为0的原因。

  接来下,虚拟机对对象进行必要的设置,例如这个对象属于哪个类的实例,如何找到类的元数据信息。对象的哈希吗、对象的GC年代等信息,这些信息都存放在对象头之中。

  执行完上面工作之后,所有的字段都为0,接着执行指令,把对象按照程序员的指令进行初始化,这样一个对象就完整的创建出来。

四,执行构造方法在执行它的有参的和无参的构造方法

猜你喜欢

转载自www.cnblogs.com/qingruihappy/p/9691340.html