太仓有没有做网站建设的,进一步优化供给推动消费平稳增长,WordPress网校系统,做网站赔钱了一.JVM运行流程
JVM向操作系统申请内存#xff0c;初始化运行时数据区#xff0c;接下来装载使用的类#xff0c;执行类里面相应方法的时候为当前虚拟机栈压入一个栈帧#xff0c;方法执行完成后栈帧出栈#xff0c;进行垃圾回收。 二.JVM中对象的创建过程 符号引用…一.JVM运行流程
JVM向操作系统申请内存初始化运行时数据区接下来装载使用的类执行类里面相应方法的时候为当前虚拟机栈压入一个栈帧方法执行完成后栈帧出栈进行垃圾回收。 二.JVM中对象的创建过程 符号引用常量池里面有一个对B对象的引用但是我们目前不知道B对象的真实地址所以我们用一个字面量去代表B对象。这就叫做符号引用。在new出A对象检查加载的时候JVM会动态解析符号引用装换为真实的地址(直接引用)。
JVM基础(四)Java类加载机制_符号引用转换为直接引用-CSDN博客
分配内存
分配内存的方式
为对象分配内存的方式有指针碰撞空闲列表。 指针碰撞适用于内存空间较为规整的情况下为A对象分配3格空间指针往后移动三格为下一个对象分配的时候当前指针位置开始分配即可。 如果内存空间不规整的话就需要用到空闲列表分配内存。JVM通过维护一张内存列表记录可用的内存块信息当分配内存时从列表中找到一个足够大的内存块分配给对象实例并更新列表上的记录。
这时候可能会有多个线程同时申请一块内存怎么解决并发安全呢CAS加失败重试和为线程分配缓冲。
解决并发安全
CAS
CAS操作包括三个操作数---内存位置、预期数值和新值。CAS的实现逻辑是将内存位置处的数值与预期数值向比较若相等则将内存位置处的值替换为新值。若不相等则不做任何处理。
CAS的操作是抱着乐观的态度进行的总认为自己可以成功完成操作当多个线程同时使用CAS操作同一个变量的时候只会有一个胜出并成功更新其他均会失败。失败的线程不会被挂起仅被告知失败并且允许再次尝试当然也允许失败的线程放弃操作。
举个例子A和B进行CASA的预期值是0新值是1B的值是0A拿到B的值0对比自己的预期值发现相同就会把1赋值给BB的值变成1这时候C的预期值是0新值是1C拿到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中直接存储的就是对象地址对象中存储了到对象类型的类型指针。
使用直接指针的方式访问速度快节省了一次指针定位的开销。