JVM中对象的创建

一.JVM运行流程

JVM向操作系统申请内存,初始化运行时数据区,接下来装载使用的类,执行类里面相应方法的时候为当前虚拟机栈压入一个栈帧,方法执行完成后栈帧出栈,进行垃圾回收。

二.JVM中对象的创建过程

符号引用:常量池里面有一个对B对象的引用,但是我们目前不知道B对象的真实地址,所以我们用一个字面量去代表B对象。这就叫做符号引用。在new出A对象,检查加载的时候,JVM会动态解析符号引用装换为真实的地址(直接引用)。

JVM基础(四):Java类加载机制_符号引用转换为直接引用-CSDN博客

分配内存

分配内存的方式

为对象分配内存的方式有指针碰撞,空闲列表。

指针碰撞适用于内存空间较为规整的情况下,为A对象分配3格空间,指针往后移动三格;为下一个对象分配的时候,当前指针位置开始分配即可。

如果内存空间不规整的话,就需要用到空闲列表分配内存。JVM通过维护一张内存列表记录可用的内存块信息,当分配内存时,从列表中找到一个足够大的内存块分配给对象实例,并更新列表上的记录。

这时候可能会有多个线程同时申请一块内存,怎么解决并发安全呢?CAS加失败重试和为线程分配缓冲。

解决并发安全

CAS

CAS操作包括三个操作数---内存位置、预期数值和新值。CAS的实现逻辑是将内存位置处的数值与预期数值向比较,若相等则将内存位置处的值替换为新值。若不相等,则不做任何处理。

CAS的操作是抱着乐观的态度进行的,总认为自己可以成功完成操作,当多个线程同时使用CAS操作同一个变量的时候,只会有一个胜出并成功更新,其他均会失败。失败的线程不会被挂起,仅被告知失败,并且允许再次尝试,当然也允许失败的线程放弃操作。

举个例子,A和B进行CAS,A的预期值是0,新值是1,B的值是0,A拿到B的值0对比自己的预期值发现相同,就会把1赋值给B,B的值变成1;这时候C的预期值是0,新值是1,C拿到B的值0发现不是自己预期的值,CAS失败。

CAS是一种CPU的指令,CPU的指令要不就执行,要不就不执行,所以具有原子性。如果是多核CPU,会有一个lock指令,保证只有一个CPU执行。

给每一个线程分配一个线程缓冲

一般分配对象都在堆的新生代的Eden区上,如果开启本地线程缓冲,如果A线程和B线程都在Eden分配对象,会分别为这两个线程在Eden区上划分一块区域,让这两个线程分配对象。

**JVM默认的方式就是线程缓冲,**如果被禁用则使用CAS

内存空间初始化

为当前对象的成员变量初始化值,比说int类型的初始化为0。

设置

针对对象头的一些设置。

对象的内存布局

类型指针:当一个对象创建的时候,在堆里面存储的对象,会有一个类型指针指向方法区里面这个对象的类型。虚拟机通过这个指针来确定这个对象是哪个类的实例。

实例数据:实例数据就是我们所赋予给对象的那些属性信息,这部分内容是紧挨着对象头存储的。

对齐填充:对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是对象的大小必须是8字节的整数倍。对象头正好是8字节的倍数(1倍或者2倍),因此当对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。

对象初始化

构造方法执行。

对象的访问定位

我们一般执行一个方法的时候,会在当前线程的虚拟机栈里面压入一个栈帧,在这个方法里面执行Person person1 = new Person,会在堆里面创建一个对象,这个person的引用会存在虚拟机栈的局部变量表里面,Person类型会存在方法区里面。堆里面的对象的类型指针会指向方法区的Person类型,局部变量表里面的person引用会指向堆里面的对象。

局部变量表里面的person引用指向堆里面的对象,存在两种方式:句柄访问和直接指针。

句柄访问

Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。

举个例子,去浴室洗澡,我们拿到搓澡师傅的手牌是13号,这个13号就相当于一个句柄,这个句柄指向的真正对象是王师傅。就相当于这个句柄就是一个代号,我们通过这个代号找到真正的搓澡师傅。

好处:句柄稳定,对象被移动只要修改句柄中的地址,不需要修改线程里面虚拟机栈的栈帧的局部变量表里面的引用。

坏处:需要开辟一块独立的空间给句柄池;同时访问对象效率较低,需要通过两次指针。

直接指针

reference中直接存储的就是对象地址,对象中存储了到对象类型的类型指针。

使用直接指针的方式,访问速度快,节省了一次指针定位的开销。

相关推荐
菜鸡且互啄6914 分钟前
在线教育平台,easyexcel使用案例
java·开发语言
八月林城15 分钟前
JAVA导出数据库字典到Excel
java·数据库·excel
浅念同学2 小时前
算法-常见数据结构设计
java·数据结构·算法
Geeker554 小时前
如何在忘记密码的情况下解锁Android手机?
android·网络·macos·华为·智能手机·电脑·手机
杰哥在此4 小时前
Java面试题:讨论持续集成/持续部署的重要性,并描述如何在项目中实施CI/CD流程
java·开发语言·python·面试·编程
wxx21505 小时前
【android】【adb shell】写一个shell脚本,监听进程pid变化
android·adb
咖啡煮码5 小时前
深入剖析Tomcat(十五、十六) 关闭钩子,保证Tomcat的正常关闭
java·tomcat
C.C5 小时前
java IO流(1)
java·开发语言
心死翼未伤6 小时前
【MySQL基础篇】多表查询
android·数据结构·数据库·mysql·算法
喂_balabala6 小时前
Android手机拍照或从本地相册选取图片设置头像-高版本适配
android·开发语言