1.对象的创建
- 虚拟机遇到new指令时,首相去检查这个指令的参数能不能在常量池定位到一个符号引用
- 保证符号引用代表的类已被加载,解析,初始化
- 虚拟机分配内存,并使内存空间初始化为零值(不包括对象头)
- 对对象进行必要的设置(这个对象是哪个类的实例,如何找到这个对象的元数据信息,对象的哈希码,GC年龄分代,偏向锁等)
- 字段初始化
- 构造代码块
- 构造方法
注:
- 如果有父类,则先父类的5,6,7,再子类的5,6,7
- static final修饰的基本类型和String为ConstantValue在【准备阶段】
- static修饰的类变量和静态代码块在【初始化阶段< clinit >()】
- 例: static A a = new A();相当于静态代码块
- 类变量和静态代码块谁先执行看位置先后(父类优先)
内存分配方式:
- Serial,ParNew等带压缩整理为指针碰撞,简单
- CMS 清除算法为空闲列表分配,复杂
线程安全问题:
- CAS加失败重试
- 本地分配缓冲区(TLAB)
2.对象的内存布局
对象在堆内存中的存储布局分为三部分:【对象头】【实例数据】【对其填充】
- 对象头:1.MarkWord 2.类型指针
- 实例数据:对象数据存在这,类数据为指针指向方法区(?)
3.对象的访问定位
通过栈上的reference数据来操作堆上的具体对象
HotSpot是第二种