本文共 1129 字,大约阅读时间需要 3 分钟。
各位兄弟们,应该都清楚,我们创建的对象都是被存放到堆中的,最后我们获得到的是一个对象的引用指针。那么有一个问题就会诞生了, JVM
创建的对象的时候,开辟了一块空间,那这个空间里都有什么东西?这个就是我们这个点的内容。
先来结论:** Java
中存在两种类型的对象,一种是普通对象,另一种是数组**
对象内存布局
我们来一个一个解释其含义。
**白话版: **对象头中包含又两个字段, Mark Word
主要存储改对象的锁信息, GC
信息等等(锁升级的实现)。而其中的 Klass Point
代表的是一个类指针,它指向了方法区中类的定义和结构信息。而 Instance Data
代表的就是类的成员变量。在我们刚刚学习 Java
基础的时候,都听过老师讲过,对象的非静态成员属性都会被存放在堆中,这个就是对象的 Instance Data
。相对于对象而言,数组额外添加了一个数组长度的属性
最后一个对其数据是什么?
我们拿一个场景来展示这个原因: **想像一下,你和女朋友周末打算出去玩,女朋友让你给她带上口红,那么这个时候你仅仅会带上口红嘛?当然不是,而是将所有的必用品统统带上,以防刚一出门就得回家拿东西!!! **这种行为叫啥? **未雨绸缪,没错,暖男行为 **。还不懂?再来一个案例。 **你准备创业了,资金非常充足,你需要注册一个域名,你仅仅注册一个嘛?不,而是将所有相关的都注册了,防止以后大价钱买域名 **。一个道理。
而对于 CPU
而言,它在进行计算处理数据的时候,不可能需要什么拿什么吧,那对其性能损耗非常严重。所以有一个协议,** CPU
在读取数据的时候,不仅仅只拿需要的数据,而是获取一行的数据,这就是缓存行,而一行是64个字节**。
所以呢?通过这个特性可以玩一些诡异的花样,比如下面的代码。
publicclassCacheLine{privatevolatileLong l1 , l2;}
我们给一个场景:两个线程 t1和t2
分别操作 l1
和 l2
,那么当 t1
对 l1
做了修改以后, l2
需不需要重新读取主内存种值。答案是一定,根据我们上面对于缓存行的理解, l1和l2
必然位于同一个缓存行中,根据缓存一致性协议,当数据被修改以后,其他 CPU
需要重新重主内存中读取数据。 这就引发了伪共享的问题
那么为什么对象头要求会存在一个对其数据呢?
HotSpot
虚拟机要求每一个对象的内存大小必须保证为8字节的整数倍,所以对于不是8字节的进行了对其补充。其原因也是因为缓存行的原因
对象=对象头+实例数据
原文:https://www.jianshu.com/p/503df66fee3e转载地址:http://atwci.baihongyu.com/