JVM整理合集②

本文主要叙叙述虚拟机内存中的数据是如何创建的?是如何布局的?以及是如何访问的等等,以HostSopt虚拟机为例,其在java堆中对象分配、布局和访问的全过程。

一、对象的创建

  1. 类加载检查:虚拟机首先会去检查指令的参数在是否在常量池中能定位到一个类的符号引用,并且进一步检查这个符号引用代表的类是否已经被加载、解析和初始化
  2. 为新生对象分配内存:有两种分配方式 

    ①指针碰撞:如果java堆内存绝对规整(说明采用的是复制算法标记-整理算法),在空闲内存和使用内存的中间放着一个指针作为分界点的指示器,分配内存的时候只需要把指针向空闲内存挪动一段和对象大小一样的距离,这样的方式称为指针碰撞。

    ②空闲列表:如果java堆内存不规整(说明使用标记-清除算法,具有碎片),虚拟机需要维护一个列表,记录哪些内存块空闲可用,分配时从空闲列表中找到一块足够大的内存给对象使用,这样的方式称为空闲列表

    特殊说明:在并发的情况下,可能出现虚拟机正在给A分配内存,指针还没来的及修改,对象B又使用了原来的指针,出现并发问题。解决的方法有两个,第一个是使用比较并交换(CAS,采用的是乐观锁实现)以及配上失败重试的方式保证操作的原子性;第二个是把内存分配的动作按线程划分在不同空间进行,即每个线程在堆中预先分配一小块内存(本地线程分配缓冲TLAB

  3. 初始化:分配完成后,为对象中的成员变量赋上初始值,设置对象头信息,调用对象的构造函数方法进行初始化。

二、对象的内存布局

     在虚拟机中,对象在内存中存储的布局主要分为3块区域:对象头、实例数据、对齐填充

  1. 对象头:包括两部分信息

    ①用于存储对象自身的运行时数据(哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向ID、偏向时间戳等),这部分被称为Mark Word,大小是4字节

    ②另一部分是类型指针:对象指向它的类元数据的指针,可以通过这个指针来确定这个对象是哪个类的实例

  2. 实例数据:这部分是对象真正存储的有效信息,在代码中所定义的各种类型的字段内容,其中包括父类成员变量和本类成员变量。

  3. 对齐填充:这部分并不是必然存在的,它只是起到了占位符的作用,因为虚拟机自动内存管理系统需要对象起始地址必须是8字节的整数倍,对象头部分正好已经是8字节的倍数了,那么当实例数据没有符合要求时,用对齐填充来补全。

三、对象的访问定位

  1. 目前的访问方式有两种,句柄访问和直接指针
    1. 句柄方式

               

         2.  直接指针访问

 需要说明的是,HotSpot 采用第二种方式,即直接指针方式来访问对象,只需要一次寻址操作,所以在性能上比句柄访问方式快一倍。但像上面所说,它需要额外的策略来存储对象在方法区中类信息的地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值