JVM-对象

对象的创建

创建一个对象很简单,开发人员只有使用new关键字创建即可,但是在虚拟机中是怎样的?

在虚拟机接收到一个new指令后必须在运行时常量池中查找是否有该对象的类型引用,如果有则在堆中分配一块连续的内存空间,如果没有则需要进行类型的加载,解析和初始化。

但是分配内存也不是简单的事儿,这个还要取决于使用的垃圾收集器回收后的空间是否规整。通常有一下两种分配方式:

  1. 指针碰撞:就是向空闲方向挪动与对象大小相等的距离,这种方式需要堆内存空间是规整的。
  2. 空闲列表:虚拟机维护一个可用空间的列表,在对象分配的时候,找到一个足够的空间分配内存,并且更新列表。使用这种方式一般来说堆空间是不规整的。

但是对空间是线程共享区域,也就意味着在创建对象为对象分配内存的时候会出现线程不安全的情况,那么如何保证线程安全呢?我想第一时间我们就能想到,加锁!锁的种类有很多即便是按照锁的力度来讲也分为轻量级锁和重量级锁。那么java虚拟机时怎么做的?

  1. CAS加上失败重试,全称CompareAndSwap,可以翻译为比较和转换。该功能Cpu原语支持,CAS本身就是原子操作。它接收两个参数,expact和update(预期值和修改值)。工作原理很好理解,当计算机接收到CAS指令时,会拿传进来的预期值和内存中的实际值进行比较,如果相同则将修改值替换实际值即可;如果在与实际值比较的时候发现预期值与实际值不同,那么就意味着在就收指令之前有其他线程对他进行了修改,这个时候重新计算预期值和修改值再次比较,直至成功。
  2. TLAB(Thread Local Alloaction Buffer)本地线程分配缓冲区。他是在创建线程的时候同时在堆内存中创建了一块线程私有的区域,当对象创建需要分配内存的时候优先在这块区域进行分配,直至超过该区域大小在到其他线程共享区域进行分配(分配过程同第一种方式)

new指令之后一般都会跟着<init>方法的执行,这个执行的就是对象的初始化方法。到这里对象在堆上的内存就已经分配完毕!

对象的结构

对象在内存中被分配以下三个部分:

对象头

对象被分配到内存中是如何定位到它的类型信息,这就要说一下对象头中锁存放的信息了。在HotSpot中对象头存放的信息如下:

  1. Mark Work
  2. 类型指针

其中Mark Work存放的是对象自身运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向锁ID和偏向时间戳等,这部分数据在32位和64位系统中分别使用32比特和64比特进行保存;然后就是类型指针,指向类型元数据的指针,Java虚拟机通过这个指针来确定该对象是那个类的实例。并非所有的虚拟机都会在对象头上存放类型指针。

​​​​​​​ 

实例数据

实例数据存放的是对象真正有效的信息,所谓有效信息就是我们在类中定义的域信息以及值,包括从父类继承来的字段,顺序并非类在定义时开发人员给定的顺序,而是按照一下默认顺序排序:long/double,int、shorts/chars、bytes/booleans、oops(引用类型)在这个默认顺序下父类域信息会被放到子类域信息之前。

对齐填充

该区域没有实际意义,在虚拟机中对象要求时8字节的整数倍,如果对象头和实例数据不足8字节的整数倍,那么该区域将会是一个占位符将整个对象的大小补充道8字节的整数倍。

 

对象如何被访问

对象在创建出来就是为了使用的,使用的地方放往往在虚拟机栈中,那么对象是在堆空间中分配那么这样的话我们应该怎样进行访问呢?

那就分为直接访问和间接访问两种:

  1. 直接指针:直接指针访问方式实现简单,访问速度,就是直接在引用对象的地方直接保存对象的引用即可。但是这样就会出现一个问题,在堆空间中对象如果移动了就需要更新所有引用它的地方的引用。
  2. 句柄访问:所谓句柄访问就是把所有的对象引用存放到一个句柄池中,使用该对象的时候只需要得到该对象在句柄池中的应用即可,这个句柄池存放了对象的引用还存放了类型指针。这样做的话在堆中对象移动后只需要修改句柄池中的引用信息即可,对栈上以及其他地方使用该对象的用户并不影响。这是它的有点但是这也是他的缺点,那就是占用空间。

HotSpot虚拟机采用的是直接指针的方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值