专业的JAVA编程教程与资源

网站首页 > java教程 正文

聊一聊java对象在内存中的存储布局(64位机)

temp10 2024-09-19 04:12:07 java教程 10 ℃ 0 评论

题外话

对于我们开发人员来说,我们经常new一个对象就拿来使用。

但是在底层具体这个对象在内存中是怎么存放的呢?

聊一聊java对象在内存中的存储布局(64位机)

可能有的人会说知道这些又有啥用呢,天天crud拧螺丝。

嗯,我也无法反驳~我的想法是知道总比不知道好,现在内卷挺严重的,比别人多知道点总归没坏处。其实这部分东西在面试中或多或少会遇到,尤其是大厂。

好了,言归正传,本次讲的是对于64位机器来说的。

首先对象分三类来说

  • 对于普通对象来说

第一个部分:对象头中8个字节的markword

第二部分:4字节的ClassPointer(默认开启压缩-XX:+UseCompressedClassPointers,不开启就是8字节)

第三部分:实例数据实际占用的字节数

第四部分:Padding对齐,8的倍数

举个栗子,这是一道面试题:问Object占用多少个字节:
Object object=new Object;
1、8个字节markword
2、默认开启指针压缩,4个字节(指向Object.class的指针)
3、没有实例数据,0个字节
4、Padding对齐意思就是前面几个部分加起来是不是8的倍数,
			前面一共12个字节,我们想让他对齐,所以再补4个字节就ok了
      所以一共是8+4+4=16个字节
  • 对于数组对象来说

和普通对象的区别在于第三部分多了一个数组长度。

举个栗子:int[] array=new int[];
1、8个字节markword
2、默认开启指针压缩,4个字节
3、数组的长度4字节
4、数组的数据,0个字节
因为8+4+4=16正好满足8的倍数,不需要对齐,所以它也占16个字节。
  • 对于含有引用类型成员变量的对象来说

什么意思呢,还是得举个栗子说明

比如我们定义一个类叫Person,它只有一个String类型的属性name。
class Person{
	 private String name;
  //省略 无参构造 和有参构造
}
1、8个字节markword
2、默认开启指针压缩,4个字节
3、此处有个成员变量name,它是引用类型String。
		 name在开启压缩-XX:+UseCompressedOops的话是4个字节,不开启就是8个字节
4、因为8+4+4=16正好满足8的倍数,不需要对齐,所以它也占16个字节。

此处需要注意的是第三部分,这里有个压缩叫UseCompressedOops,它和UseCompressedClassPointers不一样。oops意思就是ordinary object pointers。

最后我们怎么看到到底开启没开启压缩呢,可以通过下面的命令观察虚拟机的配置:

java -XX:+PrintCommandLineFlags -version

需要说明的是-XX:+PrintCommandLineFlags中的+代表开启,-就代表不开启

验证

如果想自己验证一下可以通过java agent,有一个ObjectSize.jar引入到自己项目中,然后运行时加入参数:

-javaagent:xxx\ObjectSize.jar
public static void main(String[] args) {
           System.out.println(ObjectSizeAgent.sizeOf(new Object()));
           System.out.println(ObjectSizeAgent.sizeOf(new int[] {}));
           System.out.println(ObjectSizeAgent.sizeOf(new Person("张三")));
       }

来看看打印的结果即可。


如果感觉文章对你有用,欢迎关注交流~也可收藏起来有需要的时候看看

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表