JVM阶段(2)-对象

1.对象创建

在读取对象创建的时候,我在创建过程中和类的加载过程感觉是息息相关的,好好捋一下。

在JAVA代码中,我们创建普通对象只需要通过new来进行创建。在在虚拟机底层,却包含了许多东西。

1.首先,在调用new关键字时,虚拟机此时会碰到一个new指令,首先通过这个new指令所带的参数去在常量池(.class的常量池)中去 寻找是否包含该类的符号引用,并且检查这个类的符号引用是否已经被类加载,解析和初始化。如果没有,则对当前的类执行类加载过程(加载)。

2.类加载过程通过后,会给当前对象来进行内存的分配。在分配内存时,其实就是把一块确定大小的内存从堆中取出来。这种分配内存的方式有两种,一种分配方式叫“指针碰撞”,在这种内存分配的情况下,堆中的内存是规整的。即可以理解为,有一个分界符,在分界符一侧是使用了的内存,而在另一侧则是没有使用的内存。在分配内存时,只需要移动这个分界符(指针)就可以了。另一种分配分配方式叫做“空闲列表”,即在内存中分配时,堆内部的内存是不规整的。可能前一段内存被用了,后一段内存没有被用。因为空闲内存和使用过内存不规整,所以需要一个专门的列表来对其进行维护,记录哪些空闲,哪些不空闲。对垃圾收集器有所了解的话,其实能感觉到的,第一种应用的场景是基于垃圾收集算法,标记整理法来配合使用的。第二种,是和标记清除法结合,来进行使用的。

考虑一下线程安全,在不做线程安全的情况下,上述所说的指针碰撞内存分配方式,A对象内存分配后,还没有移动分界符指针。此时B对象分配内存,然后分界符指针改变。这个时候A再在原有基础上移动分界符指针,就覆盖了B对象了。所以为了解决这种方式,一种的话,就是使用CAS来保证分配内,分界指针移动是一个原子性操作,另一种的话,就是内存分配在不同空间来执行,也就是线程在JAVA堆中预先分配一小块内存(Thread Local Allocation Buffer,我不清楚这个说是不是线程分配的1M内存),哪个线程分配内存,就在哪个缓冲区存放。

3.在分配完内存之后,来对分配到的内存空间全部都设置为零值(除了对象头)。这个过程其实就是保证对象的实例字段在不被人为赋值时也可以参与使用的。(就是类的加载机制中的准备操作)

4.在对分配号内存的对象赋值类型初始值,还需要一些必要设置。这些设置依赖于对象头,就markword,klass。就像当前对象所属类型,分代年龄,hash码,以及元数据信息等。都是通过对象头实现的。

5.上述过程,其实就已经创建好一个对象了。不过,这个对象来不是我们用的对象。在之后来需要执行字节码中的<init>方法,也就是构造函数。只有构造函数执行后,才是真正可用的对象(类加载机制中的初始化操作)。

2.对象的内存布局

对象在堆中其实主要划分做了三点,对象头,实例数据以及对象填充。

对象头,这个我之前在线程中学过的,包含三类,markword,klass以及array length。

普通对象只有markword,klass,数组会多一个array length。

mark word,存储的是对象的运行数据,如hash码,GC分代年龄,锁状态标识,线程持有的锁,偏向ID,还有偏向状态等等。这个我知道,不做太多阐述。

klass,指向类型元数据的指针,即可以通过对象头中klass来找到当前对象所属的类型。

array length,就是当前数组的长度没什么意义。

对象填充,没什么意义,这个不需要记。

3.对象的定位访问

对象后续的引用访问,只要采用的是reference来进行各类访问的。在书中是这么介绍的。试着看了下reference的源码,是一个抽象类,具体的行为步骤是在封装在一个内部类handler中完成的。没有完全看下去。先知道有这么个东西。

对象基于reference来进行访问,主要有两种方式,一种是句柄方式,另一种则是直接指针方式。句柄方式指的是,在java堆(注意是堆)中分配出一块专门的空间来存储句柄,句柄中包含了对象实例数据的地址信息以及类型实例数据的句柄信息。而直接指针的方式则是reference中直接存取对象地址信息与类型地址信息,这样的话访问速率较快,但对象每次垃圾回收整理位置,reference信息都得变动。hotspot虚拟机用的其实是直接指针方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值