简体   繁体   English

Java Array使用多少内存?

[英]How much memory does a Java Array use?

I'm trying to find out how much memory an array uses inside of the JVM. 我试图找出一个数组在JVM内部使用了多少内存。 I've set up a program for that purpose, which is giving me odd results. 我为此目的设立了一个程序,这给了我奇怪的结果。

protected static long openMem(){
    System.gc();
    System.runFinalization();
    return Runtime.getRuntime().freeMemory();
}

public static double listSize(int limit){
    long start= openMem();
    Object[] o= new Object[limit];
    for(int i= 0; i<limit; i++ ){
        o[i]= null;
    }
    long end= openMem();
    o= null;
    return (start-end);
}

public static void list(int i){
    for(int y= 0; y<50; y++ ){
        double d= Quantify.listSize(i);
        System.out.println(i+" = "+d+" bytes");
    }
}

public static void main(String ... args){
        list(1);
        list(2);
        list(3);
        list(100);
    }

When I run this, I get two different byte-sizes for each size of array, like: 当我运行它时,我为每个数组大小得到两个不同的字节大小,如:

  • 1 = 24.0 bytes 1 = 24.0字节
  • 1 = 208.0 bytes 1 = 208.0字节
  • 1 = 24.0 bytes 1 = 24.0字节
  • 1 = 208.0 bytes 1 = 208.0字节
  • 1 = 208.0 bytes 1 = 208.0字节
  • 1 = 208.0 bytes 1 = 208.0字节
  • 1 = 208.0 bytes 1 = 208.0字节
  • 1 = 24.0 bytes 1 = 24.0字节

So an array of 1 element only ever returns "24 bytes" or "208 bytes", and the same pattern holds for all others: 因此,只有1个元素的数组才能返回“24个字节”或“208个字节”,并且相同的模式适用于所有其他元素:

1 = 24.0 bytes 1 = 24.0字节

1 = 208.0 bytes 1 = 208.0字节

2 = 24.0 bytes 2 = 24.0字节

2 = 208.0 bytes 2 = 208.0字节

3 = 32.0 bytes 3 = 32.0字节

3 = 216.0 bytes 3 = 216.0字节

100 = 416.0 bytes 100 = 416.0字节

100 = 600.0 bytes 100 = 600.0字节

I'm trying to figure out why that is. 我想弄清楚为什么会这样。 What I'm wondering is whether anyone else here (a) already knows the answer, or (b) knows how to find the answer. 我想知道的是这里是否有其他人(a)已经知道答案,或者(b)知道如何找到答案。

Measuring heap occupancy on the JVM is even trickier than measuring performance. 测量JVM上的堆占用比测量性能更复杂。 For one, there are thread-local allocation buffers (TLABs), which are chunks of heap allocated at once regardless of object size being allocated. 例如,有线程局部分配缓冲区 (TLAB),它们是一次分配的堆块,无论分配的对象大小如何。 You should disable their use for measurement: -XX:-UseTLAB . 您应该禁用它们用于测量: -XX:-UseTLAB Further, your code does some things right but others only almost right. 此外,您的代码做了一些正确的事情,但其他人只是几乎正确。 I would for example suggest running two GC's; 我会建议运行两个 GC; no need to run finalization; 无需进行最终确定; and run a GC before allocation, then after deallocation. 并在分配之前运行GC,然后在重新分配之后运行。 You run it only before each measurement. 您只能在每次测量之前运行它。 You also need to use totalMemory-freeMemory , otherwise you are vulnerable to heap resizing. 您还需要使用totalMemory-freeMemory ,否则您很容易受到堆大小调整的影响。

All in all, try measuring with this code, it gives me reliable results. 总而言之,尝试使用此代码进行测量,它为我提供了可靠的结果。

class Quantify {
  static final Object[][] arrays = new Object[20][];

  static long takenMem(){
    final Runtime rt = Runtime.getRuntime();
    return rt.totalMemory() - rt.freeMemory();
  }

  static long arraySize(int size){
    System.gc(); System.gc();
    long start = takenMem();
    for (int i = 0; i < arrays.length; i++) arrays[i] = new Object[size];
    final long end = takenMem();
    for (int i = 0; i < arrays.length; i++) arrays[i] = null;
    System.gc(); System.gc();
    return (end - start) / arrays.length;
  }
  public static void main(String... args) {
    for (int i = 1; i <= 20; i++) System.out.println(i+": "+arraySize(i));
  }
}

I get this output: 我得到这个输出:

1: 24
2: 24
3: 32
4: 32
5: 40
6: 40
7: 48
8: 48
9: 56
10: 56
11: 64
12: 64
13: 72
14: 72
15: 80
16: 80
17: 88
18: 88
19: 96
20: 96

This is consistent with the real situation: the minimum allocation is 24 bytes due to the overhead of headers; 这与实际情况一致:由于报头的开销,最小分配为24字节; sizes change by 8 due to memory alignment concerns (this is typical for a 64-bit JVM). 由于内存对齐问题,这些大小会改变8(这对于64位JVM来说是典型的)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM