栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

并发编程(二十九) - 对象的内存布局

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

并发编程(二十九) - 对象的内存布局

文章目录
  • 一、对象的内存布局
    • 1. 对象在堆内存中的存储布局
    • 2. 对象头(Header)
      • 2.1 Mark Word
        • (1) Mark Word 存储结构
        • (2) Mark Word 存储信息
      • 2.2 类元信息(又叫类型指针)
      • 2.3 对象头在OpenJDK中C++源码
    • 3. 实例数据(Instance Data)
    • 4. 对齐填充(Padding)
    • 5. 演示创建一个对象所需内存大小
    • 6. GC分代年龄
    • 7. 压缩类型指针

一、对象的内存布局 1. 对象在堆内存中的存储布局
  • 在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding,保证8个字节的倍数)
  • 对象头分为对象标记(Mark Word在OpenJDK中叫markOop)和类元信息(ClassPointer在OpenJDK中叫klassOop),类元信息存储的是指向该对象类元数据(klass)的首地址

2. 对象头(Header) 2.1 Mark Word (1) Mark Word 存储结构
  • 在64位系统中,Mark Word占了8个字节,类型指针占了8个字节,一共是16个字节
(2) Mark Word 存储信息
  • 默认存储 对象的HashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等信息
  • 这些信息都是与对象自身定义无关的数据,所以MarkWord被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的数据
  • 它会根据对象的状态复用自己的存储空间,也就是说在运行期间MarkWord里存储的数据会随着锁标志位的变化而变化
2.2 类元信息(又叫类型指针)
  • 对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
2.3 对象头在OpenJDK中C++源码
  • oop.hpp源码
_mark字段是mark word,_metadata是类指针klass pointer,对象头(object header)即是由这两个字段组成
  • markOop.hpp源码
hash: 保存对象的哈希码
age: 保存对象的分代年龄
biased_lock: 偏向锁标识位
lock: 锁状态标识位
JavaThread* :保存持有偏向锁的线程ID
epoch: 保存偏向时间戳
3. 实例数据(Instance Data)
  • 存放类的属性(Filed)数据信息,包括父类的属性信息
4. 对齐填充(Padding)
  • 虚拟机要求对象起始地址必须是8字节的整数倍
  • 填充数据不是必须存在的,仅仅是为了字节对齐。这部分内存按8字节补充对齐
5. 演示创建一个对象所需内存大小
  1. 导入依赖


    org.openjdk.jol
    jol-core
    0.9

  1. 测试Object,不带实例数据
public class JOLDemo{
    public static void main(String[] args){
        Object o = new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
    }
}
OFFSET: 偏移量,也就是到这个字段位置所占用的byte数
SIZE: 类型的字节大小
TYPE: Class中定义的类型
DESCRIPTION: 类型的描述
VALUE: TYPE在内存中的值

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header) (前8个字节是mark word)                          00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)  (注意:这里类型指针为4个字节)                          e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment) (再加4个字节对齐填充,凑满8的倍数)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
  1. 测试User,带实例数据
public class JOLDemo{
    public static void main(String[] args){
        User u = new User();
        System.out.println(ClassLayout.parseInstance(u).toPrintable());
    }
}
cn.lwk.test.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
     12     4                int User.age                                  0
     16     1            boolean User.flag                                 false
     17     3                    (alignment/padding gap)                  
     20     4   java.lang.String User.name                                 null
Instance size: 24 bytes
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total
6. GC分代年龄
  • GC年龄采用4位bit存储(二进制1111最大是15),最大为15,例如MaxTenuringThreshold参数默认值就是15

测试:
手动设置 -XX:MaxTenuringThreshold=16

启动程序后报错:

Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
MaxTenuringThreshold of 16 is invalid; must be between 0 and 15
7. 压缩类型指针
  • 使用 java -XX:+PrintCommandLineFlags -version 打印 HotSpotVM 采用的自动优化参数
PS D:下载并发编程代码concurrentjmh_performancetarget> java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=265765696 -XX:MaxHeapSize=4252251136 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers(默认开启了压缩类型指针) -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+U
seParallelGC
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
  • -XX:+UseCompressedClassPointers(默认开启了压缩类型指针,所以类型指针所占内存大小为4个字节)

测试:
手动设置 -XX:-UseCompressedClassPointers,关闭压缩指针

public class JOLDemo{
    public static void main(String[] args){
        Object o = new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
    }
}
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)    (前8个字节为mark word)                       00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)    (关闭压缩指针,则后8个字节为类型指针)                       00 1c 4d 1c (00000000 00011100 01001101 00011100) (474815488)
     12     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1006197.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号