数组和链表-内存存储分析
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
- 在Java中,对象的内存布局和对齐与C/C++中的情况略有不同,但"gap"的概念仍然存在。
- 在Java中,"gap"通常指的是在对象的内存布局中,为了满足对齐规则而产生的未使用的空间。这与C/C++中的情况类似,但Java的内存模型和垃圾回收机制与C/C++有所不同,因此对象的内存布局和对齐方式也有所不同。
- 在Java中,对象的内存布局通常包括对象头、实例数据和对齐填充。对象头包含对象的元数据信息,实例数据包含对象的字段值,对齐填充是为了满足JVM的对齐规则而产生的未使用的空间。
- 需要注意的是,Java中的对象对齐规则和填充方式可能会因JVM的实现和版本而有所不同。因此,在不同的JVM或不同的Java版本上,同一个对象的内存布局和对齐方式可能会有所不同。
?7、对象头的作用
在Java中,对象头(Object Header)是Java对象在内存中的元数据部分,它记录了对象的元信息,如类的元信息、哈希码、GC标记等。对象头的作用主要有以下几个方面:
- 记录类的元信息:对象头中存储了对象的类信息,包括类的元数据、类加载器信息等。这些信息用于确定对象的类型和行为。
- 存储哈希码:对象头中存储了对象的哈希码,用于支持Java的哈希表实现。哈希码是对象在哈希表中的索引,用于快速查找和比较对象。
- GC标记:对象头中存储了GC标记信息,用于垃圾回收器跟踪和管理对象。当垃圾回收器需要回收内存时,会通过GC标记来判断哪些对象需要被回收。
需要注意的是,Java中的对象头是JVM内部管理的,对于Java程序来说是透明的。程序员不需要直接操作对象头,只需要关注对象的实例数据即可。
?
文章来源:https://blog.csdn.net/m0_65152767/article/details/135024363
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!