流程
- new 对象之后,先看方法区的常量池中是否有类的符号引用
- 如果没有,那么加载类(todo),完成之后就知道我们需要申请多少空间了
- 堆中申请空间
- 初始化,基本对象为0,引用对象为null
- 调用< init > 构造方法
内存分配问题
两种方案
- 使用指针碰撞:可用内存跟不可用内存之间有个指针,可用跟不可用内存是规整的
- 使用空闲列表:空闲区域的指针放入链表中
线程安全问题
假如线程1有个a对象,线程2有个b对象,a正在申请的时候,b也开始申请,堆是共享的,会有线程安全问题。
两种方案:
- 每次分配内存都加锁
- 堆中按线程分区域(线程缓存区),申请线程缓存区的时候加锁
对象的内存布局
- 对象头
- 运行时数据(对象的hashcode,gc年代,锁状态等)
- 类指针(指向方法区中的类信息,表明该对象是哪个类)
- 实例数据
- 对齐填充padding
Hotspot对象访问定位
栈中有堆对象的引用,堆对象中有方法区中对象类型数据(class)的引用
tip:还有一种是句柄的方式
堆中有句柄池跟对象池,栈中有句柄池的引用,句柄池中有对象的引用跟对象类型数据(class)的引用
参考 《深入理解jvm》49页