Java中布尔型变量的大小是多少?

89
有人能告诉我在Java中,boolean类型的位数是多少吗?

1
这里也有同样的问题:https://dev59.com/iHI-5IYBdhLWcg3wVWzv - dma_k
8个回答

185

这取决于虚拟机,但可以轻松地从一个关于Java字节的类似问题中的代码进行适应

class LotsOfBooleans
{
    boolean a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    boolean b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    boolean c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    boolean d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    boolean 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
    {        
        LotsOfBooleans[] first = new LotsOfBooleans[SIZE];
        LotsOfInts[] second = new LotsOfInts[SIZE];

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

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

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

        System.out.println ("Size for LotsOfBooleans: " + (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 ? 1 : 0) + second[i].a0;
        }
        System.out.println(total);
    }

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

再次强调,这取决于虚拟机,但在我运行Sun的JDK版本1.6.0_11的Windows笔记本电脑上,我获得了以下结果:

Size for LotsOfBooleans: 87978576
Average size: 87.978576
Size for LotsOfInts: 328000000
Average size: 328.0

这表明Sun的JVM基本上可以将布尔值打包成每个字节。


21
@skeet - 我非常敬佩你。你的回答很棒。 - Warrior
2
@warrior:由于我已经有了“byte”的代码,所以将其更改为“boolean”非常简单 :) - Jon Skeet
3
System.gc()不能保证清理内存。它只是向JVM发出垃圾回收的命令,但这并不意味着收集器实际上清理了任何东西。记住,收集器清理未使用的对象。如果程序不再持有对对象的引用,则该对象未使用。因此,在测试中,我建议在运行gc()之前通过将LotsOfBooleans设置为null显式地丢弃引用;或者只需使用布尔值一次,整型一次进行一次主要运行,然后比较数字即可。 - Randa Sbeity
2
@RandaSbeity 或者更好的是:确保保留两个引用并计算内存差异。这正是这里发生的事情。 - biziclop
1
Jon Skeet 无法回答的问题吗? - Andreas Hartmann
对于不熟悉的人来说,输出中的那些数字需要除以80,因为类中有80个元素,才能得到答案所断言的最终结果。 - flow2k

41

这取决于虚拟机。


9
可以指出一些文档吗?我很难相信布尔值的大小是取决于机器的。这意味着包含布尔值的类的二进制表示在不同的虚拟机中具有不同的大小(和内存布局),这将意味着虚拟机之间不兼容。 - David Rodríguez - dribeas
14
我认为这个问题暗示着询问布尔变量在内存中的大小,而不是编码在类文件中的大小。根据Sun的文档,内存中的大小因虚拟机而异。而类文件中的大小是恒定不变的。 - William Brendel
3
在Java 1.1时期左右,Sun JVM在将布尔值存储为实例或自动变量时使用4个字节。这简化了字节码解释器的实现(它将布尔类型视为占用栈上的4个字节),也是最小阻力的路径。当我们实现iSeries“Classic”JVM时,我们找到了使实例变量为1个字节的方法,因为这大大提高了某些对象的紧凑性(这对性能有惊人的影响)。显然,根据下面的帖子,Sun/Oracle的开发人员后来也找到了实现类似功能的方法。 - Hot Licks
但是,截至2017年底,JavaDocs指出:“boolean:布尔数据类型...此数据类型表示一位信息,但其“大小”并没有明确定义”--但您的观点是正确的,它可能需要一些链接和更好的信息 :) - JimLohse

31
Java中布尔值所代表的实际信息是一个位:true为1,false为0。然而,在内存中布尔变量的实际大小并没有被Java规范精确定义。详见Java中的原始数据类型
布尔数据类型只有两个可能的值:true和false。用于跟踪true/false条件的简单标志使用此数据类型。该数据类型表示一位信息,但它的“大小”并没有被精确定义。

21

顺带一提...

如果您考虑使用布尔对象数组,请不要这样做。相反,使用BitSet - 它具有一些性能优化(和一些很好的附加方法,允许您获取下一个设置/未设置的位)。


这并不总是正确的。https://dev59.com/xXRB5IYBdhLWcg3wgHWr - Przemek
那个回答表明使用boolean[]的重要原因,但正如那里的评论所指出的那样,没有太多支持它的证据。话虽如此:我不怎么用Java编程(也没有提供任何证据;) - Matthew Schinckel

6

我读到Java为boolean数据类型保留了一个字节,但实际上只使用了一位(bit)。然而,文档中说“它的‘大小’并没有被精确定义”请参见此处。


这是一个教程,不是“文档”。文档包括JLS、JVM规范和Javadoc。 - user207421

2

boolean值在JVM中被编译为int数据类型。点击这里查看更多信息。


2
这并不一定是它们在内存中的存储方式,我认为这就是提问者想知道的。那个文档描述了类文件格式(编译后的字节码),而不是内存中布尔变量的表示,因为这取决于具体实现。 - William Brendel

2

Java中的布尔类型大小取决于虚拟机。 但是,任何Java对象都会按照8字节的粒度对齐。一个布尔类型有8字节的头部和1字节的有效负载,总共占用9字节的空间。JVM会将其向上舍入到下一个8的倍数。 因此,java.lang.Boolean的一个实例占用16字节内存。


我倾向于不同意,在HotSpot JVM 1.7.0_51上,标头有12个字节+1个布尔值+3个粒度。 - Eugene
14
不要混淆 Boolean 和 boolean。 - andresp
1
字节还是位?一个布尔值占用16个字节太浪费了...这相当于一个长整型的大小,而长整型可以携带比布尔值多一万亿倍的信息。 - Dici

0

它是未定义的;像Jon Skeet建议的那样做会在给定平台上得到一个近似值,但要精确地了解特定平台的情况,最好使用分析器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接