一、创建对象的方式
- new、Xxx的静态方法、XXXBuilder/XXXFactory的静态方法
- Class的newInstance,只能调用空参构造器,权限必须是public
- Construct的newInstance,可以调用空参、带参的构造器,权限无要求
- Clone(),不调用构造器,但需要实现Cloneable接口,实现clone,默认浅拷贝
- 使用反序列化
二、创建对象的过程
- 判断对象对应类是否加载、链接、初始化
- 为对象分配内存(指针碰撞、空闲列表)
- 处理并发安全问题
- 初始化分配到的内存
- 设置对象头
- 执行init方法进行初始化
三、对象结构
对象头
对象头主要包含元数据和类型指针
元数据
- 对象哈希值
- GC分代年龄
- 锁状态标志
类型指针:指向方法区中该对象的类元信息
四、执行引擎
将字节码指令解释/编译为对应平台的机器码
动态编译
简单来说就是将java代码编译成字节码文件,再由执行引擎动态的将字节码转换成机器码
解释器
特点:预热快,速度慢
逐行将字节码翻译成机器码
JIT编译器
特点:预热慢,速度快
将热点代码的机器码进行缓存,方便下次直接调用,但若一开始就使用JIT,由于缓存需要额外耗费时间和空间,速度反而要差于解释器,也会额外增加内存消耗
热点代码触发的两种方式
- 方法调用计数器:用来记录一段时间内方法的调用次数,超过这段时间若还没达到阈值则次数减半
- 回边计数器:记录一个方法内循环体的执行次数
静态编译
直接将java文件编译成机器码,但这样做会带来两个问题:
- 违反了一次编译,到处运行的特点,因为编译出来的机器码只能在一种操作系统上使用
- 失去了动态编译的优化