Java对象的创建、内存分配和访问

Student student = new Student();

student.study();

(1)对象的创建

①检查new指令的参数是否能在常量池中定位到一个类的符号引用,检查符号引用代表的类是否已经加载、解析和初始化

  类的加载机制

②虚拟机为新生对象分配内存,对象所需内存的大小在类加载之后即可确定(从Java堆中分配一块内存)

  指针碰撞:堆内存是规整的,用过的内存放一边,空闲内存放另一边,中间放一个指针作为分界点,分配时,只需要移动指针即可

  空闲列表:堆内存是不规整的,虚拟机维护一个列表,记录那些内存是可用的,哪些内存是不可用的,分配时,从列表中找一块足够大的内存,并更新列表

    堆内存是否规整,取决于JVM采用的垃圾回收器是否有压缩整理功能

  多线程环境下,内存分配是否线程安全(虽然只是修改一个指针)?

    a.对分配内存的动作进行同步处理(CAS+失败重试)

    b.为每个线程分配一个本地线程缓冲区(TLAB)

③将分配到的内存空间初始化为零值

④设置对象的对象头

  对象是那个类的实例、如何找到对象的云数据、对象的哈希码、对象的GC分代年龄

⑤执行<init>方法,按照程序员的意愿进行初始化

(2)对象的内存布局

①对象头

a.运行时数据:哈希码、GC分代年龄、锁状态标志、线程持有的锁等

d.类型指针,对象指向它的类元数据的指针,表明这个对象是哪个类的实例

②实例数据

程序中定义的字段(包括从父类继承的)

存储顺序:虚拟机分配策略(long/double , int , short/char , byte , boolean, 引用)、定义的顺序(父类在子类之前)

③对齐填充

(3)对象的访问定位

对象实例数据&对象类型数据

①使用句柄访问

Java堆中分配一块内存,作为句柄池

对象的引用指向稳定的句柄,对象移动只需改变句柄中实例数据指针

句柄中有指向对象实例数据和对象类型数据的指针

②直接访问

对象的引用直接指向对象实例数据

对象实例数据中有指向对象类型数据的指针

直接访问开销小

原文地址:https://www.cnblogs.com/duanjiapingjy/p/9438015.html