数组和链表-内存存储分析

2023-12-15 21:38:57

1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.atguigu</groupId>
        <artifactId>data-structure-alg</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>demo01-array</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.17</version>
        </dependency>
    </dependencies>

</project>

2、ClassLayout.parseInstance(new Object()).toPrintable()

        //查看对象在内存中是如何保存的?
        Object o = new Object();
        //获取对象的布局转为可以输出的字符串 打印
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4        (object header: class)    0x00000d58
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

这段代码是用来打印Java对象的内部布局信息的。具体来说,它使用了ClassLayout类的parseInstance方法来解析一个Object实例的布局,并打印出相应的信息。

输出中的内容描述了对象的内存布局:

  • OFF?和?SZ?分别表示对象在内存中的偏移量和大小。
  • TYPE DESCRIPTION?提供了对象的类型描述。
  • VALUE?是与每个字段关联的值。

从输出中可以看到:

  • 对象头(object header)的 标记(mark)字段位于偏移量0,大小为8字节。synchronized加锁:必须通过对象加锁
  • 对象头的类(class)字段位于偏移量8,大小为4字节。类模板对象的引用,类模板存在方法区(元空间MetaSpace)中,对象可以通过该位置的地址获取到类模板对象
  • 对象头后面有一个4字节的空隙,可能是用于对齐。
  • 实例大小(Instance size)为16字节。
  • 内部空间损失(Space losses)为0字节,外部空间损失为4字节。

需要注意的是,输出的信息可能因JVM的实现和版本而有所不同。因此,如果你在不同的JVM或不同的Java版本上运行此代码,可能会得到不同的输出结果。

3、ClassLayout.parseInstance(new int[5]).toPrintable()

        //int类型数组的值占的内存:4*5=20byte
        int[] ints = new int[5];
        System.out.println(ClassLayout.parseInstance(ints).toPrintable());

?

[I object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4        (object header: class)    0x000065f8
 12   4        (array length)            5
 16  20    int [I.<elements>             N/A
 36   4        (object alignment gap)    
Instance size: 40 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

4、?ClassLayout.parseInstance(new long[5]).toPrintable()

        //long类型数组的值占的内存:8*5=40byte
        long[] longs = new long[5];
        System.out.println(ClassLayout.parseInstance(longs).toPrintable());
[J object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4        (object header: class)    0x00001160
 12   4        (array length)            5
 16  40   long [J.<elements>             N/A
Instance size: 56 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

?5、ClassLayout.parseInstance(new LinkedList<>()).toPrintable()

        LinkedList<Integer> list = new LinkedList<>();
        Collections.addAll(list, 1, 2, 3, 4, 5);
        System.out.println(ClassLayout.parseInstance(list).toPrintable());
java.util.LinkedList object internals:
OFF  SZ                        TYPE DESCRIPTION               VALUE
  0   8                             (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4                             (object header: class)    0x001ef218
 12   4                         int AbstractList.modCount     5
 16   4                         int LinkedList.size           5
 20   4   java.util.LinkedList.Node LinkedList.first          (object)
 24   4   java.util.LinkedList.Node LinkedList.last           (object)
 28   4                             (object alignment gap)    
Instance size: 32 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?6、object alignment gap

  1. 在Java中,对象的内存布局和对齐与C/C++中的情况略有不同,但"gap"的概念仍然存在。
  2. 在Java中,"gap"通常指的是在对象的内存布局中,为了满足对齐规则而产生的未使用的空间。这与C/C++中的情况类似,但Java的内存模型和垃圾回收机制与C/C++有所不同,因此对象的内存布局和对齐方式也有所不同。
  3. 在Java中,对象的内存布局通常包括对象头、实例数据和对齐填充。对象头包含对象的元数据信息,实例数据包含对象的字段值,对齐填充是为了满足JVM的对齐规则而产生的未使用的空间。
  4. 需要注意的是,Java中的对象对齐规则和填充方式可能会因JVM的实现和版本而有所不同。因此,在不同的JVM或不同的Java版本上,同一个对象的内存布局和对齐方式可能会有所不同。

?7、对象头的作用

在Java中,对象头(Object Header)是Java对象在内存中的元数据部分,它记录了对象的元信息,如类的元信息、哈希码、GC标记等。对象头的作用主要有以下几个方面:

  1. 记录类的元信息:对象头中存储了对象的类信息,包括类的元数据、类加载器信息等。这些信息用于确定对象的类型和行为。
  2. 存储哈希码:对象头中存储了对象的哈希码,用于支持Java的哈希表实现。哈希码是对象在哈希表中的索引,用于快速查找和比较对象。
  3. GC标记:对象头中存储了GC标记信息,用于垃圾回收器跟踪和管理对象。当垃圾回收器需要回收内存时,会通过GC标记来判断哪些对象需要被回收。

需要注意的是,Java中的对象头是JVM内部管理的,对于Java程序来说是透明的。程序员不需要直接操作对象头,只需要关注对象的实例数据即可。

?

文章来源:https://blog.csdn.net/m0_65152767/article/details/135024363
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。