JVM --- 对象的创建步骤

目录

1.先看常量池里面有没有该对象,如果有用常量池中的

2.看这个类有没有被加载过,如果没有,先加载类到方法区中。对象的大小在类加载的时候就确定了

3.对象在堆内存里面的划分,有指针碰撞和空闲列表两种方式

4.jvm会创建对象头信息,new指令之后会接着执行构造方法创建出对象


1.先看常量池里面有没有该对象,如果有用常量池中的

2.看这个类有没有被加载过,如果没有,先加载类到方法区中。对象的大小在类加载的时候就确定了

3.对象在堆内存里面的划分,有指针碰撞和空闲列表两种方式

        ①、指针碰撞:在Java堆内存为绝对工整的前提下,被使用过的内存放在一遍,没有使用过的放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间方向挪动一段与对象大小相等的距离(一个对象的内存绝对是连续的,如果不是跟内存存储单位的整数倍,就会产生内存碎片)。而Java堆是否规整又由所采用的垃圾收集器是否带有空间压缩整理(Compact)的能力决定。

        ②、空闲列表:不是规整的,已经使用的和没有使用的交错,虚拟机用一个列表标记哪块内存为空闲。需要单独分配空间记录

        ③、并发情况下需要注意步骤是不是原子性,如果不是原子性,一定要加锁。(读地址和存信息是两个步骤,读和写分别都是原子性,但两者加起来不是,可能会产生重叠)

        ④、指针碰撞在并发的情况下不是线程安全的,解决方法:

                a、一种是对分配内存空间的动作进行同步处理——实际上虚拟机是采用CAS配上失败重试的方式保证更新操作的原子性

                b、另外一种是把内存分配的动作按照线程划分在不同的空间之中进行。即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local AllocationBuffer,TLAB),哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。(牺牲空间来换取时间,减少同步的次数)                                         ⑤、new出来的对象里面都存什么(例如这个对象是哪个类的实例、如何才能找到 类的元数据信息、对象的哈希码(实际上对象的哈希码会延后到真正调用Object::hashCode()方法时才 计算)、对象的GC分代年龄等信息。这些信息存放在对象的对象头(Object Header)之中。根据虚拟 机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

4.jvm会创建对象头信息,new指令之后会接着执行构造方法创建出对象

猜你喜欢

转载自blog.csdn.net/qq_52240237/article/details/131946810