java虚拟机中的对象

对象创建过程图:

给对象分配内存

1.指针碰撞图:

解读:

(1).我们把堆内存分为两个空,一个是我们使用的内存,另一个是空闲的内存,中间放一个指针为分界线,其实分配内存,就是指针移动的过程。当我们创建一个对象的时,它肯定会占用内存空,那么外面使用的内存就会增大,空闲内存就会减少,所以指针就会往左移动。这种分配方式称之为指针碰撞。

(2).空闲列表:在Java堆中内存并不是规整的,已使用的内存,和空闲的内存并不像(1)中那么完整,而是这一块是使用的,另一块是未使用的,或是相互交叉的。那么这种情况就没法使用我们上述的指针碰撞了。这时,虚拟机就必须维护一个列表,记录哪些内存块是可用的,在分配区域的时候就从这张表里找到这个区域给这个对象的实例,分配了以后就将这块内存从表里面删掉,这么一个运行过程称之为空闲列表。

对象结构:

  1. Header(对象头)

           (1).自身运行时数据(Mark Word):包括哈希值,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等等。

           (2)类型指针:就是对象指向它的类的源数据的一个指针,而并非是一定需要这个指针的

  1. InstanceData(对象数据的示例):这一部分是存储对象的有效信息,不管是从父类继承下来的,还是从子类定义的,都需要记录起来。这部分的存储顺序会受到虚拟机分配的策略和字段在Java源码中定义的顺序影响。那么虚拟机所默认的分配策略,是使相同宽度的字段分配到一起。在满足这个条件之后,父类定义的变量可以能会出现在子类之前。
  2. Padding:这部分的数据并不是必然存在的,也没有特别的含义,它仅仅相当于占位符。为什么要占位符?主要是因为虚拟机自动内存管理系统要求对象启始地址必须是8个字节的整数倍,而对象头部分正好是8给字节的整数倍,因此对象数据示例部分没有对其启始,那么就需要Padding来填充。

对象的访问定位:

Java虚拟机规范中,这个引用类型,仅仅规定了一个指定向对象的引用,并没有定义这个引用通过何种方式去定位访问堆中对象的具体位置。所以对象的访问方式有以下两种实现方案。

1.使用句柄:

               好处:在栈内存中的引用是固定的,栈内存存储的地址是永远不改变的,变的只是句柄池中的地址

2.直接指针:

              好处:速度非常快,减少线程的开销,性能是非常高的

示意图:

猜你喜欢

转载自www.cnblogs.com/wangjiachun2017/p/10332032.html
今日推荐