美文网首页
Java 对象占用内存空间

Java 对象占用内存空间

作者: 杰哥长得帅 | 来源:发表于2019-02-07 11:31 被阅读13次

集合框架存的都是对象引用,而不是对象本身

在 Java 中,一个空 Object 对象的大小是 8 byte,这个大小只是保存堆中一个没有任何属性的对象的大小

Object ob = new Object();

这样在程序中完成了一个 Java 对象的生命,但是它所占的空间为:4 byte + 8 byte。4 byte 是上面部分所说的 Java 栈中保存引用的所需要的空间。而那 8 byte 则是 Java 堆中对象的信息。因为所有的 Java 非基本类型的对象都需要默认继承 Object 对象,因此不论什么样的 Java 对象,其大小都必须是大于 8 byte(上面是 32 位操作系统,64 位是 8 + 16)

Java 对象的内存布局

Java 对象的内存布局:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)

对象头

对象头在 32 位系统上占用 8 bytes,64 位系统上占用 16 bytes

实例数据

原生类型(primitive type)的内存占用如下:

Primitive Type Memory Required(bytes)
boolean 1
byte 1
short 2
char 2
int 4
float 4
long 8
double 8

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

对齐填充

HotSpot 的对齐方式为 8 字节对齐:

(对象头 + 实例数据 + padding)% 8 等于 0 且 0 <= padding < 8

指针压缩

对象占用的内存大小收到 VM 参数 UseCompressedOops 的影响

对对象头的影响

开启(-XX:+UseCompressedOops)对象头大小为 12 bytes(64 位机器)

class A {
    int a;
}

A 对象占用内存情况:

  • 关闭指针压缩: 16 + 4 = 20 不是 8 的倍数,所以加 padding(4) = 24
  • 开启指针压缩: 12 + 4 = 16 已经是 8 的倍数了,不需要再加 padding

对 reference 类型的影响

64 位机器上 reference 类型占用 8 个字节,开启指针压缩后占用 4 个字节

class B  {
    int b2a;
    Integer b2b;
}

B 对象占用内存情况:

  • 关闭指针压缩: 16 + 4 + 8 = 28 不是 8 的倍数,所以加 padding(4) = 32
  • 开启指针压缩: 12 + 4 + 4 = 20 不是 8 的倍数,所以加 padding(4) = 24

数组对象

64 位机器上,数组对象的对象头占用 24 个字节,启用压缩之后占用 16 个字节。之所以比普通对象占用内存多是因为需要额外的空间存储数组的长度

先考虑下 new Integer[0] 占用的内存大小,长度为 0,即是对象头的大小:

  • 未开启压缩:24 bytes
  • 开启压缩后:16 bytes

new Integer[3] :

  • 未开启压缩:24(对象头)+ 8 * 3 = 48,不需要 padding
  • 开启压缩:16(对象头)+ 4 * 3 = 28,加 padding(4) = 32

自定义类的数组也是一样的:

class B3 {
    int a;
    Integer b;
}

new B3[3] 占用的内存大小:

  • 未开启压缩:48
  • 开启压缩后:32

复合对象

计算复合对象占用内存的大小其实就是运用上面几条规则,只是麻烦点

对象本身的大小

直接计算当前对象占用空间大小,包括当前类及超类的基本类型实例字段大小、引用类型实例字段引用大小、实例基本类型数组总占用空间、实例引用类型数组引用本身占用空间大小; 但是不包括超类继承下来的和当前类声明的实例引用字段的对象本身的大小、实例引用数组引用的对象本身的大小

class B {
    int a;
    int b;
}
class C {
    int ba;
    B[] as = new B[3];

    C() {
        for (int i = 0; i < as.length; i++) {
            as[i] = new B();
        }
    }
}
  • 未开启压缩:16(对象头)+ 4(ba)+ 8(as 引用的大小)+ padding(4) = 32
  • 开启压缩:12 + 4 + 4 + padding(4) = 24

当前对象占用的空间总大小

递归计算当前对象占用空间总大小,包括当前类和超类的实例字段大小以及实例字段引用对象大小

递归计算复合对象占用的内存的时候需要注意的是:对齐填充是以每个对象为单位进行的

C 对象占用内存,主要是三部分构成:C 对象本身的大小 + 数组对象的大小 + B 对象的大小

  • 未开启压缩:
    (16 + 4 + 8 + 4(padding)) + (24 + 8 * 3) + (16 + 8) * 3 = 152 bytes

  • 开启压缩:
    (12 + 4 + 4 + 4(padding)) + (16 + 4 * 3 + 4(数组对象 padding)) + (12 + 8 + 4(B对象padding))* 3 = 128 bytes

相关文章

  • 【Java进阶营】虚拟机研究系列-Java各种类型对象占用内存情

    内容简介 本文深入分析并验证了不同Java对象占用内存空间大小的情况。对于不同的jvm实现,Java对象占用的内存...

  • Java 对象占用内存空间

    集合框架存的都是对象引用,而不是对象本身 在 Java 中,一个空 Object 对象的大小是 8 byte,这个...

  • Garbage Collection GC

    java垃圾回收回收的是什么 对无用对象的回收 清理掉 腾出他所占用的内存空间 JVM的内存区域 程序计数器 占用...

  • JVM入门——类的大小

    一般大部分java程序并不知道一个java类到底占用了多少内存空间,下面我就分析一下一个java对象在堆中到底占用...

  • iOS之OC对象占用多少内存

    NSObject对象占用多少内存空间 一个NSObject对象都会分配16byte的内存空间,通过源码可以知道: ...

  • Java对象占用内存空间分析及实战

    最近在做一个需求,评估Java列表10万数据加载到内容占用空间大小,以及对服务器内存使用影响。以前都是从书上看Ja...

  • Java编程中对象内存空间占用分析

    Java编程中,了解对象的内存开销非常重要。本文主要分析Java语言中对象的内存占用。 1、Java对象内存占用简...

  • OC对象本质

    1.内存空间占用 一个NSObject对象占用多少内存?系统分配了16个字节给NSObject对象(通过mallo...

  • C++对象模型探索

    2021.7.19 2.1 类对象所占用的空间 成员函数不占用类对象的内存空间,每个类只诞生 一个(跟着类走)一个...

  • 什么样的JAVA对象才是大对象

    需要占用大量连续内存空间的jaa对象是大对象,比如很长的字符串和数组。 理解误区: 1.需要占用大量非连续空间的j...

网友评论

      本文标题:Java 对象占用内存空间

      本文链接:https://www.haomeiwen.com/subject/mndljqtx.html