1.对象是如何创建的
在语言层面上,new一个对象;
1.1 类加载
在虚拟机中,先检查new这条指令的类是否被加载过,如果没有,就进行类加载
1.2 分配内存
1.2.1 分配内存的两种方式
- java堆规整,指针碰撞
- 不规整,空闲列表
java堆是否规整与采用的垃圾收集器是否有压缩整理功能有关。
1.2.2 线程安全处理方案
并发情况下线程并不安全
- 对分配内存空间的动作进行同步处理——实际上虚拟机采用CAS(比较再交换指令)配上失败重试的方式保证更新操作的原子性
- 把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(TLAB)
1.3 分配到的空间都初始化为零值
1.4 虚拟机对对象进行必要的设置
例如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的GC分代年龄等。
———————————————————————————
从虚拟机角度看,对象创建完成,但从java程序看,还需执行〈init〉方法,把对象按照程序员的意愿初始化,对象创建完成
2.对象的内存布局
2.1 对象头
对象头包括两部分的信息,一部分存储对象自身运行时的数据信息,称为“Mark Word”,对象不同状态下,存储的内容不同;另一部分为类型指针,虚拟机通过它确定这个对象是哪个类的实例。
2.2 实例数据
对象真正存储的有效信息,程序代码中所定义的各种类型的字段内容
2.3 对齐填充
不是必然存在的,起着占位符的作用
3.对象的访问定位
3.1 句柄访问
reference(GC检测到会被回收的对象)中存储对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息
使用句柄来访问的最大好处就是reference中存储的是稳定的句柄地址,在对 象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要修改。
3.2 直接访问
reference中存储的直接是对象地址
使用直接访问的好处就是速度更快