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


Answers:


41

它取决于虚拟机。


9
想要指出一些文档?我很难相信布尔值的大小取决于机器。这意味着包含布尔值的类的二进制表示形式在不同的VM中将具有不同的大小(和内存布局),这意味着VM将不兼容。
大卫·罗德里格斯(DavidRodríguez)-德里贝斯

14
我认为这暗示问题在于内存中的布尔变量的大小,而不是在类文件中编码的布尔变量的大小。根据Sun的文档,内存的大小因VM而异。类文件中的大小是恒定的。
威廉·布伦德尔

3
@DavidRodríguez-dribeas-Java 1.1左右的Sun JVM作为实例或自动var存储时,使用4个字节的布尔值。这简化了字节码解释器的实现(它认为布尔值在堆栈中占据4个字节),并且是阻力最小的路径。当我们实施iSeries“经典” JVM时,我们发现了使实例变量为1字节的方法,因为这大大提高了某些对象的紧凑性(这对性能产生了惊人的影响)。显然,基于下面的帖子,Sun / Oracle开发人员想出了如何在更高版本中执行同样的操作。
Hot Licks

但这是正确的,截至2017年底JavaDocs表示:boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined-但您的观点是正确的,它可以使用一些链接和更好的信息:)
JimLohse

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();
    }
}

重申一下,这取决于VM,但是在运行Sun的JDK build 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:因为我已经有了“字节”的代码,所以将其更改为“布尔值”非常简单:)
Jon Skeet

3
System.gc()不保证清除内存。它只是给JVM一个命令以运行垃圾回收,但这并不意味着该垃圾回收器实际上已经清理了一些东西。请记住,收集器会清理UNUSED对象。如果程序不再保存对该对象的引用,则该对象未使用。因此,在您的测试中,我将通过在运行gc()之前将LotsOfBooleans设置为null来显式删除引用。或只使用布尔值一次运行main,一次使用int运行一次,然后比较数字。
Randa Sbeity 2014年

2
@RandaSbeity甚至更好:确保保留两个引用并计算内存差异。这正是这里发生的情况。
biziclop

1
有什么问题乔恩·斯凯特(Jon Skeet)无法回答吗?
Andreas Hartmann

31

在Java中,由布尔值表示的实际信息是一位:1表示true,0表示false。但是,Java规范没有精确定义内存中布尔变量的实际大小。请参见Java中的原始数据类型

布尔数据类型只有两个可能的值:true和false。将此数据类型用于跟踪真/假条件的简单标志。这种数据类型代表一小部分信息,但是其“大小”并不是精确定义的。


21

在侧面说明...

如果您正在考虑使用布尔对象数组,则不要。改用BitSet-它具有一些性能优化(以及一些不错的额外方法,可让您获得下一个置位/未置位)。



该答案表明使用boolean []的理由很重要,但是正如那里的注释所表明的那样,没有太多可备份的内容。话虽这么说:我不使用Java
编写

6

我读到Java为boolean数据类型保留了一个字节,但只使用了一位。但是,文档说“其“大小”不是精确定义的”看这里。


那是一个教程,而不是“文档”。该文档是JLS,JVM规范和Javadoc。
洛恩侯爵,

2

这些booleanint在JVM中被编译为数据类型。看这里


2
这并不一定是它们在内存中的存储方式,我认为这是提出问题的人想知道的。该文档描述了类文件格式(编译后的字节码),而不是内存中布尔变量的表示形式,因为这与实现有关。
威廉·布伦德尔

2

Java中布尔值的大小取决于虚拟机。但任何Java对象均以8字节的粒度对齐。布尔值具有8个字节的标头和1个字节的有效负载,总共有9个字节的信息。然后,JVM将其舍入为8的下一个整数倍。因此,java.lang.Boolean的一个实例占用16个字节的内存。


我会倾向于不同意,在HotSpot JVM 1.7.0_51上,标头包含12个字节+ 1个布尔值+ 3个粒度。
尤金

14
不要将布尔值与布尔值混淆。
andresp

1
字节还是位?16字节的数据包Boolean真是太浪费了……它的大小long可以承载比a更大的万亿倍的信息Boolean
Dici

0

它是未定义的;像Jon Skeet所建议的那样进行操作将使您在给定的平台上获得近似值,但是要精确了解特定平台的方法是使用探查器。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.