1.虚拟机内存区域
2.对象的创建
3.对象的内存布局
4.如何访问对象
1.虚拟机内存区域
虚拟机 = 程序计数器 + 虚拟机栈 + 本地方法栈 + 堆 + 方法区(常量池,直接内存)
程序计数器:记录字节码指令的位置
虚拟机栈:存放局部变量
本地方法栈:为本地Native方法服务
堆:实例对象(是垃圾回收的主要区域)
方法区:常量,静态变量等
2.对象的创建
(1).查看常量池是否存在
(2).如果常量池没有,用类加载机制加载
(3).为对象分配内存
1).内存分配策略 = 指针碰撞 + 空闲列表
指针碰撞:当内存是整齐的一边有数据,另一边没数据时,将指针向没数据的那边移动对象大小的距离
空闲列表:当内存不整齐时,用一个列表记录哪些是空闲内存。
2).线程安全问题 = 同步 + 本地线程缓冲区
本地线程缓冲区:在堆中给线程加一个缓冲区,用到缓冲区内存分配对象时,没有线程安全问题
(4).将对象的值置零
(5).虚拟机进行一些必要的设置:对象hash值,垃圾回收分代,说明这个对象是哪个类的实例
(6).执行程序员的<init>方法
3.对象的内存布局 = 对象头 + 实例数据 + 对齐填充
(1).对象头 = 对象本身的数据 + 类型指针
对象本身的数据:hash值,锁,gc分代
类型指针:对象指向类元数据的指针
(2).对齐填充:没有什么实际作用,主要保持格式完整
4.如何访问对象
首先需要明确:对象实例数据放在堆中,对象的类型放在方法区中
访问对象通过栈的reference来访问,访问方式有2种
(1).直接访问对象实例数据,对象实例数据中包含了指向对象类型的指针,通过这个指针指向对象类型
(2).通过第三方,这个第三方我们称作句柄。句柄包含了对象实例数据的指针和对象类型的指针。通过访问句柄访问对象实例数据和对象类型。(句柄也是在堆中)