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堆中分配一块内存,作为句柄池
对象的引用指向稳定的句柄,对象移动只需改变句柄中实例数据指针
句柄中有指向对象实例数据和对象类型数据的指针
②直接访问
对象的引用直接指向对象实例数据
对象实例数据中有指向对象类型数据的指针
直接访问开销小