对象再内存中的布局-对象的创建和对象的结构,对象的访问定位

1对象的创建:如下表

主要问题:(类的加载后面会详细讲到)    虚拟机到底是如何为对象分配内存的呢?如何往堆中去进行?在分配内存时会出现一些线程安全问题,如何决解?

1.1 给对象分配内存:堆是一块不连续的存储空间(假设堆内存规整的,用过的在一边空闲的在另一边,中间有指针,分配内存就是指针在移动的过程)

1.1.1指针碰撞分配内存

1.1.2:空闲列表:堆内存一般都是不规整的,一些使用一些未使用,虚拟机会维护一个列表来记录哪些内存快快是可用的

在分配的时候就可以从这张表里面去找出来这快区域,给这个对象用并更新在这个表中。

到底选择哪种分配方式就是由内存是否规整来决定的,而Java中的堆是否规整是由垃圾回收策略来决定的

当垃圾回收策略会自动的进行垃圾回收整理,把内存划分非常规整的就可以用指针碰撞了。

1.2线程安全问题:(1)线程同步,加锁,执行效率低  (2)本地线程分配缓冲:每一个线程单独的为它分配一个区域(可以通过虚拟机参数指定)如图:


2,对象的结构:

     2.1.Header(对象头): 存储对象的元数据 ,就是如何来找到对象等等都是存在对象头中的

            2.1.1:自身运行时数据 (Mark Word电脑多少位就是多少位存储)  哈希值  GC分代年龄 锁状态标志 线程持有锁 偏向线程ID 偏向时间戳


             2. 1.2:类型指针:对象指向类的元数据的指针(可有可无)后面讲解

2.2:InstanceData:存储对象的有效信息,存储顺序会受到虚拟机的分配策略和在Java源码中定义的影响,默认的分配的

策略是相同的字段被分配到一起。如(long.double     short/char  在满足这个前提之下在父类定义的变量会出现在子类之前)

2.3.Padding;对其填充 相当占位符,起始地址必需要是8个字节的整数倍,而对象头部正好是8字节的

整数倍

3对象的访问定位

3.1:使用句柄;指向队中的一个区域(句柄池),句柄池:保存了实例对象的地址

        栈指向的地址(引用地址)永远是句柄池的地址 永远不会变。不过以后对象是不是被回收。

3.2:直接指针;速度快,减少一次寻址开销。图解如下:




猜你喜欢

转载自blog.csdn.net/qq_32170289/article/details/81006582