• java内存之对象的内存布局和访问定位


    对象内存布局和访问定位初见

     

    在HotSpot虚拟机中,对象在内存中的布局可分为3块区域:对象头、实例数据、对齐补充

     

    对象头:

      包括两部分信息,第一部分用于存储对象自身的运行时数据(哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向时间id、偏向时间戳等),这部分数据在32位和64位虚拟机中所占空间分别为32bit和64bit,官方称其为“Mark Word”,Mark Word被设计成一个非固定的数据结构以便在极小的空间存储尽量多的信息,它会根据对象的状态复用自己的内存空间。

      对象头的另一部分时类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

    实例数据:

      对象真正存储的有效信息。存储顺序受到虚拟机分配策略参数和字段在Java源码中定义顺序的影响。HotSpot虚拟机默认的分配策略为longs/doubles、ints、shorts/chars、bytes/booleans、oops。即相同宽度的字段总会被分配在一起。在满足这个前提条件的情况下,在父类中定义的变量会出现在子类之前。

    对齐补充:不是必然存在的。起着占位符的作用。因为对象的大小必须为8字节的整数倍,主要用于对于实例数据部分的补齐。

     

    注:

    并不是所有的虚拟机实现都必须在对象数据上保留类型指针,也就是说,查找对象的元数据信息不一定要经过对象本身(涉及到对象访问定位的两种不同方式)

    如果对象是一个java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通java对象的元数据信息确定java对象的大小,但是从数组的元数据中无法确定数组的大小(有待深入研究)

    对象访问定位的两种不同方式

    首先在栈中会有一个reference数据,通过它来操作具体对象。对象访问方式有两种:使用句柄和直接指针

    句柄访问:在java堆上划分出一个区域作为句柄池,而reference数据中存的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自具体的地址信息,这种方式即为查找对象的元数据信息不一定要经过对象本身的情况。这种方式好处是当对象移动时不需更改reference数据,只需更新句柄池

    直接指针访问:reference数据中存放的就是对象地址,而对象中有到对象类型的指针来存储对象类型数据的地址。这种方式好处时速度快,因为此种方式减少了一次指针操作。

     

  • 相关阅读:
    再次或多次格式化导致namenode的ClusterID和datanode的ClusterID之间不一致的问题解决办法
    Linux安装aria2
    POJ 3335 Rotating Scoreboard 半平面交
    hdu 1540 Tunnel Warfare 线段树 区间合并
    hdu 3397 Sequence operation 线段树 区间更新 区间合并
    hud 3308 LCIS 线段树 区间合并
    POJ 3667 Hotel 线段树 区间合并
    POJ 2528 Mayor's posters 贴海报 线段树 区间更新
    POJ 2299 Ultra-QuickSort 求逆序数 线段树或树状数组 离散化
    POJ 3468 A Simple Problem with Integers 线段树成段更新
  • 原文地址:https://www.cnblogs.com/xuhan74520/p/13518692.html
Copyright © 2020-2023  润新知