JVM对象创建过程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mozha_666/article/details/82529168

问题:在语言层面,通过new一个关键字就可以创建一个对象,那么在底层jvm是如何进行一个对象的创的??
1)首先程序计数器在收到这个new得到指令时候,先到方法区的常量池检查有没有这个类的符号引用,然后检查类是否加载解析初始化过没有就进行类加载
2)类加载完成后,JVM就要在java堆上为对象分配内存,这个内存大小是在类加载的时候就确定的,从java堆中分配内存有两种方式一个指针碰撞,一个空闲列表方式,两种方式各有优点
3)初始化,JVM将分配到的内存区域初始化为零值,这个操作保证了对象的实例字段可以不赋初始值就可以使用,然后对对象头数据进行设置(对象分为3部分内容)
4)执行方法,这个方法其实就是实现构造函数的赋值内容,对数据进行初始化,到此一个对象的创建就完成了

扩展点:
java堆内存分配的两种方式:
1)指针碰撞,什么是指针碰撞,我们假设java堆是规整的,用过的内存放一边,没用的放另一边当需要分配内存时移动指针
2)空闲列表,当java堆是不规整的,JVM维护一个列表,上面记录着哪些内存块是可用的,当需要分配内存就从上面取一块下来
3)那么选择哪种分配方式,首先看java堆是否规整,java堆是否规整取决了选择了哪种垃圾收集器,有些垃圾收集器带有压缩整理的功能比如serial parNew垃圾收集器,那么他的java堆就是规整的,就采用指针碰撞方式像CMS收集器都采用空闲列表方式

对象的内存布局
1)对象在内存中的布局可分为3个部分,对象头,实例数据,对齐填充
2)首先对象头有两部分数据Mark word 和类型指针,Markword 存储了哈希码 GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID等 ,这部分数据的长度在32/64虚拟机中分别为32bit和64bit,Mark word被设计成一个非固定数据结构,根据对象的状态复用自己的空间;类型指针指向类元数据的指针,用来确定这个对象是哪个类的实例;如果对象是一个数组,对象头还要有一个块用于记录数组长度的数据
3)实例数据,其实就是对象中定义的字段以及从父类继承的数据
4)对齐填充只是起到占位作用目的是为了使对象的大小是8字节的整数倍,这是因为HotSpotVM 的自动内存管理系统要求对象起始地址必须是8字节的整数倍

对象访问定位
1)对象创建完后放在java堆中 ,那么用的时候虚拟机怎么找到这个对象,句柄方式和直接指针方式
2)句柄的话,java堆中会划分一个区域叫句柄池,那么引用类型reference中存储的就是对象的句柄地址,句柄包含了对象实例数据类型的具体地址信息
3)直接地址方式,reference存储的就是对象的地址
4)两种方式对比,句柄的话,reference存的是句柄地址,对象移动只是修改句柄中的对象地址,reference内的数据就不用改,直接指针的方式就是速度更快

猜你喜欢

转载自blog.csdn.net/mozha_666/article/details/82529168