`
zl198751
  • 浏览: 272980 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java对象占内存大小

阅读更多

 

空对象占8个字节 
有数据成员的话,你把数据成员按基本数据类型和对象引用分开统计。 
基本数据类型按byte/boolean=1,char/short=2,int/float=4,long/double=8,累加,然后对齐到8的倍数。 
对象引用按每个4字节,累加,然后对齐到8个字节的倍数。 
============= 
对象占用字节数=基本的8字节+基本数据类型所占的+对象引用所占的 

比如 
class A{ 
int a; 
char b; 

占 8(基本)+8(int 4+char 2=6,对齐到8)= 16个字节 
再比如: 
class B{ 
Integer a; 
long b; 
byte c; 

占 8(基本)+8(long8+byte1=9,对齐到8)+8(对象引用4,对齐到8)=32个字节 

=============== 
如果你是从别的类继承的,父类的也要算上。

这与C++不同,C++中,空对象占一个字节,有数据成员则按数据成员对齐后,得到的大小

#include <iostream.h>
class A
{
private:
int i;
    char b;
};

void main()
{
A a;
cout<<sizeof(a)<<endl;
}

得到的是8

 

 

 

数组的内存计算:

Java中对象的内存使用量(Heap Memory Usage)

通常情况下Hotspot虚拟机里Heap(堆)中的Java对象占用的内存包括:

  • Object Header占用的内存普通对象的Object Header占用8个字节的内存,数组对象的Object Header占用12个字节的内存(其中的4个字节用于存储数组的长度)
  • 成员变量占用的内存
    • 基本数据类型的成员变量(primitive field),boolean/byte类型耗用1个字节,char/short类型耗用2个字节,int/float类型耗用4个字节,long/double类型耗用8个字节
    • 对象类型的成员变量(reference field),每个变量一个4个字节的reference
  • Padding(对齐)需要的额外内存,padding部分是紧跟在object data后面的若干(0~7)个字节,使得整个对象耗用的字节数能被8整除。
  • 于是对象占用的内存大小可以用下面的公式进行估算:

    sizeof(obj) = ceil((sizeof(object header) + sum(sizeof(primitive field)) + 4*num(reference field))/8)*8

    例如,对于下面一个Class:

    class MyClass { // 8 bytes (object header)
      byte a;        // 1 byte
      int c;           // 4 bytes
      boolean d;    // 1 byte
      long e;        // 8 bytes
      Object f;     // 4 bytes (reference)
    }

    不考虑padding(对齐)的情况下该类的实例大约占用26(8 + 1 + 4 + 1 + 8 + 4)个字节,进行padding后将占用32个字节的空间。

    注意:这里估算的内存占用大小并不包括对象类型的成员变量所占用的内存大小,这里只计算reference占用的内存大小。

    一维数组的内存占用量:
    在Java里数组也是对象,且数组对象的Object Header比普通对象的要多4个字节,这4个字节是用来存储数组长度用的。另外数组对象也会被Padding(补齐)。

    基本数据类型的数组对象占用的内存大小可以用下面的公式进行估算:

    sizeof(array) = ceil((12 + sizeof(primitive field)*m)/8)*8 #m为数组的长度

    如长度为10的int类型的数组int[10]占用的内存大小为: ceil((12 + 4*10)/8)*8 = 56

    对象数组Object[]占用的内存大小可以用下面的公式进行估算:

    sizeof(Object[]) = ceil((12 + 4*m)/8)*8

    4*m中的4表示每个Object reference占用的内存大小,4个字节;m表示数组的长度。

    再例如,对于String类:

    public final class String {   // 8 bytes (object header)
    private final char value[]; // 4 bytes (reference)
    private final int offset;   // 4 bytes
    private final int count;    // 4 bytes
    private int hash;           // 4 bytes
    }

    一个包含n个字符的String对象整体(包括char[]数组)占用的内存大小为:

    sizeof(string) = ceil((8 + 4 + 4 + 4 + 4)/8)*8 + ceil((12 + 2*n)/8)*8

    二维数组的内存占用量:
    Java中的二维(多维)数组与C语言中的二维(多维)数组有非常大的不同。Java中的二维(多维)数组是由nested数组构成的一个级联结构,二维(多维)数组中的每一行都是一个reference指向的nested数组。

    于是对于一个m*n的二维数组array[m][n],它的内存占用量包括下面两部分:
    1个长度为m的外层数组占用的内存,可以表示为:ceil((12 + 4*m)/8)*8
    m个长度为n的内存数组占用的内存,可以表示为:m*(ceil((12 + sizeof(nested_array_type)*n)/8)*8)
    对于基本数据类型的二维数组,sizeof(nested_array_type)为对应基本数据类型的内存使用量
    对于Object[][],sizeof(nested_array_type)等于4个字节,即reference的内存使用量

    例如,对于int类型的二维数组int[m][n],它的内存占用量估算为:
    ceil((12 + 4*m)/8)*8 + m*(ceil((12 + 4*n)/8)*8)
    假设(m=1000000, n=3),则该二维数组的内存占用量为:
    ceil((12 + 4*1000000)/8)*8 + 1000000*(ceil((12 + 4*3)/8)*8) = 28,000,016

    结论:尽量避免长期持有(引用)大规模的二维数组对象

     

     

     

     

     

     

     

    分享到:
    评论

    相关推荐

    Global site tag (gtag.js) - Google Analytics