在java层面,创建对象是new操作,在jvm中首先要根据这个指令的参数定位常量池中此类符号的引用,
并且检查引用代表的这个类是否已被加载/解析/初始化过。如果没有,那么会先执行相应的类加载过程。
类加载后,要为新生对象分配内存。
对象所需内存的大小在类加载完后便可完全确定。
创建新对象就是在堆内存中划出一块空内存使用。
这又分为两种情况:
if(java堆内存绝对规整){
内存模型大概是这样的:【空闲内存区域】【分界点指针】【已使用内存区域】;
new操作会让指针往空闲内存区域移动一块相应大小的距离,称为【指针碰撞】;
}else if(java堆内存不规整){
虚拟机会维护一个列表,记录哪些空闲内存可用;
new操作jvm会分配一块足够大的内存,并更新列表的记录,称为【空闲列表】;
}
当jvm创建对象的时候,如果遇到了并发,一般也有两种处理方法:
1·cas加上失败重试保证更新操作的原子性。
2·将堆中要分配的内存【线程私有化】。为每个线程预先分配一块内存,使用【TLAB】。
内存分配完成后,虚拟机将分配到的内存空间初始化为零值。
保证了实例字段在代码中不用初始化就直接使用,程序访问对象时默认访问的零值,例如刚初始化的string类型不需要初始化,值为null。
分配好对象的内存后,虚拟机对对象进行必要的设置,设置对象的【头信息:包括元数据信息,对象hashcode,对象的GC分代情况等】
new到此结束,加上init方法,一个对象的初始化就完成了。
对象的内存布局:。
【对象头】:包括自身运行的相关数据,以及【类型指针(指向元类型),充分非必要条件】
【示例数据】:包括数据的值。
【对齐填充】:非必要存在,主要是占位符作用。
对象的访问定位:
【使用句柄】:【对象实例指针】去堆中查找,【对象类型指针】去方法去中找,并行。
【直接指针】:【对象实例指针】去堆中查找,然后【对象类型指针】去方法去中找,类似于链表。