内存中一个字节的大小 - Java

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (18)

我听说了一个字节在java程序中占用的内存量的不同意见。

我知道你可以在java字节中存储不超过+127字节的数据,并且文档中说一个字节只有8位,但在这里我被告知它实际上占用与int相同数量的内存,因此只是一种有助于代码理解而不是效率的类型。

任何人都可以解决这个问题,并且这会是一个实现特定的问题吗?

提问于
用户回答回答于

好的,有很多讨论,并没有太多的代码:)

这是一个快速的基准。当涉及到这种事情时,它会得到正常的警告 - 由于JITting等原因,测试内存具有奇怪的特征,但是适当地大的数字无论如何都是有用的。它有两种类型,每种都有80个成员 - LotsOfBytes有80个字节,LotsOfInts有80个成员。我们建立了很多它们,确保它们不是GC'd,并检查内存使用情况:

class LotsOfBytes
{
    byte a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    byte b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    byte c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    byte d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    byte e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}

class LotsOfInts
{
    int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    int c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    int d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    int e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}


public class Test
{
    private static final int SIZE = 1000000;

    public static void main(String[] args) throws Exception
    {        
        LotsOfBytes[] first = new LotsOfBytes[SIZE];
        LotsOfInts[] second = new LotsOfInts[SIZE];

        System.gc();
        long startMem = getMemory();

        for (int i=0; i < SIZE; i++)
        {
            first[i] = new LotsOfBytes();
        }

        System.gc();
        long endMem = getMemory();

        System.out.println ("Size for LotsOfBytes: " + (endMem-startMem));
        System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));

        System.gc();
        startMem = getMemory();
        for (int i=0; i < SIZE; i++)
        {
            second[i] = new LotsOfInts();
        }
        System.gc();
        endMem = getMemory();

        System.out.println ("Size for LotsOfInts: " + (endMem-startMem));
        System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));

        // Make sure nothing gets collected
        long total = 0;
        for (int i=0; i < SIZE; i++)
        {
            total += first[i].a0 + second[i].a0;
        }
        System.out.println(total);
    }

    private static long getMemory()
    {
        Runtime runtime = Runtime.getRuntime();
        return runtime.totalMemory() - runtime.freeMemory();
    }
}

在我的盒子上输出:

Size for LotsOfBytes: 88811688
Average size: 88.811688
Size for LotsOfInts: 327076360
Average size: 327.07636
0

所以显然有一些开销 - 看起来它有8个字节,虽然对LotsOfInts来说只有7个字节(就像我说的,这里有些古怪) - 但问题是字节字段似乎被LotsOfBytes打包,使得它(在高架移除之后)仅占LotsOfInts的四分之一内存。

用户回答回答于

是的,一个字节变量实际上是4个字节的内存。然而这并不适用于数组。实际上,20字节的字节数组在内存中只有20个字节。这是因为Java字节码语言只知道int和long是数字类型(所以它必须处理所有数字都是4字节或8字节的任何一种),但它知道每个可能数字大小的数组(所以短阵列在事实上每个条目和字节数组中的两个字节实际上是每个条目一个字节)。

扫码关注云+社区