java的对象需要多少钱_估算一个Java对象要占用多少内存

估算一个Java对象要占用多少内存。Java对象在JVM中的构成。

开始

今天我们来聊聊,一个Java对象,到底在内存占据多大的空间?

2c5e9ebe630262b3ad57198fb482a53a.png对象

堆和栈

Java在程序运动时,内存空间根据功能不同,可以分成五块,分别是寄存器,本地方法区,方法区,堆,栈。

单以堆和栈来说,栈中主要存放的是基本数据类型,局部变量等,new 创建的实例对象或数据,则存放在堆中。

对于栈来说,每个线程有自己独立的栈。线程结束,栈就会消失(空间就会被回收。事实上,不需要等待线程结束,随着入栈和出栈,方法运行结束,方法相关的内容就会消失)。而堆,则是大家共享的。实例对象或数据,即使不再使用,也有可能不会马上消失。因为堆内存的回收是依靠垃圾回收机制的。

对象头

Java对象,一般由三部分构成,分别是对象头,实例数据和对象填充。

对象头一般有Mark Word、指向类的指针,数组对象会多出一部分,用于存放数组长度。

Mark Word主要存放对象的一些基本信息,如GC标记,锁信息等。一般情况下,在32位JVM占据32bit,在64位JVM占据64bit。

指向类的指针一般也是32bit或64bit。这个东西的作用就是标记实例对象属于哪个类。我们知道,Class对象在类加载时,会放到方法区,那么,指向类的指针事实上指向的是方法区中Class对象存放的地址。

数组长度保存数组对象的长度。只有数组对象才有此内容,长为32bit。

对象填充

因为实例对象比较复杂,所以我们先来介绍对象填充。在JVM中,所有对象占用的内容空间都是8bit的整数倍。如果不足,就要补充。用于补充的内容是没有意义的。

实例数据

实例数据,一般是对象的类属性部分。这部分内容,根据类型的不同,占用内存的大小也不同。

3b642d0a8dca3681c1e9ef674407606c.png

reference类型在32位系统上每个占用4bytes, 在64位系统上每个占用8bytes。

这里,有两个点需要注意:

1. byte和bit不是一个概念。bit是位,二进制位,是计算机中衡量空间的最小单位。byte为字节,一个字节,通常为8位,即1byte = 8bit。

2. reference类型即引用类型。什么是引用类型?不是基本类型就是引用类型。换句话说,除了上面表中列的8种,其它都是引用类型,包含String,包装类等。

综上,我们得出,计算一个对象占用内存的大小,可以先把实例数据部分的大小算出来,再加上对象头的大小,最后,在取大于等于结果的最小的8的倍数。注意,实例数据部分算完后要换算成bit。

聊到这里,有同学心里就会有一些疑问:上面的内容,只说了对象头和对象的属性,那么对象的方法哪儿去了?难道对象的方法不需要占用内存来存储吗?

很好,如果你有这个疑问,说明你经过了认真的思考。确实,对象的方法也是需要存储的,要不然,程序怎么知道某个方法具体的操作?但是,这部分内容并不是存储在实例对象上的,而是存储在Class对象上的。要执行某个方法时,程序根据对象头中的指向类的指针,就能找到Class对象,就能找到对应的方法。换做你来设计Java,你应该也不会把这部分内容放到实例对象上,因为同一个类的所有实例对象,他们的方法逻辑是同样的。也就是说,存一份就足够了,没必要搞那么多。

指针压缩

为了减小对象对内存空间的占用,JVM允许对象UseCompressedOops参数,来设置开启指针压缩。

开启指针压缩后,主要会对对象头和引用类型产生影响。开启压缩后,对象头占用空间变成12个字节,如果是数组对象,会是16个字节(多的4个字节用于存储数组长度)。引用类型由原来的8字节变成4个字节。

计算对象大小

假设当前运行环境是一个未开启指针压缩的64位JVM。我们尝试计算一个普通实例对象的大小。

首先,对象头大小为64bit,这个是没有问题的。

然后,我们开始计算实例数据。计算实例数据时,如果一个类继承了另一个类,那么,根据继承的规则,事实上,父类的非private属性,也要计算进来,如果有同名属性,以当前类为准。

最好,将对象头大小和实例数据大小相加,再扩展到8的倍数,即得到了对象的大小。

到此,我们能够通过计算,得到了一个对象的内存大小。但是,事实上,我们漏掉了一些对象。比如,A对象中包含一个属性,B b = new B()。那么,B对象占用的空间,是否也算做A对象的大小呢?严格来说,不应该计算,因为b只是一个引用,而不是对象本身。但是,一般情况下,不会遇到说去估算某个对象在内存中大小的场景,更多的时候,是让我们估计某个程序或某段代码在运行时,占用内存的大小,这个时候,就必须去考虑每个对象的每个引用所指向的具体对象了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值