¿Cuál es el tamaño de una variable booleana en Java?

89

¿Alguien puede decir el tamaño de bit de boolean en Java?

DonX
fuente
1
Lo mismo se pregunta aquí: stackoverflow.com/questions/1907318/…
dma_k

Respuestas:

41

Depende de la máquina virtual.

Guerrero
fuente
9
¿Le importaría señalar algunos documentos? Me cuesta creer que el tamaño de un booleano dependa de la máquina. Eso significaría que la representación binaria de una clase que contiene un booleano tendría diferentes tamaños (y diseños de memoria) en diferentes VM y eso implicaría que las VM no serían compatibles.
David Rodríguez - dribeas
14
Creo que estaba implícito que la pregunta se refiere al tamaño de una variable booleana en la memoria, no al tamaño de una variable booleana codificada en un archivo de clase. El tamaño de la memoria varía según la máquina virtual según la documentación de Sun. El tamaño en el archivo de clase es constante.
William Brendel
3
@ DavidRodríguez-dribeas - La JVM de Sun en la época de Java 1.1 usaba 4 bytes para booleano cuando se almacenaba como una instancia o auto var. Esto simplificó la implementación del intérprete de código de bytes (que considera que los bools ocupan 4 bytes en la pila) y fue el camino de menor resistencia. Cuando implementamos la JVM iSeries "Classic", encontramos formas de hacer vars de instancia de 1 byte, ya que eso mejoró enormemente la compacidad de algunos objetos (lo que tiene un impacto asombroso en el rendimiento). Aparentemente, según las publicaciones a continuación, los desarrolladores de Sun / Oracle descubrieron cómo hacer lo mismo en versiones posteriores.
Hot Licks
Pero es correcto, a finales de 2017, los JavaDocs dicen: boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined- pero su punto es válido, podrían usar algunos enlaces y mejor información :)
JimLohse
185

Depende de la máquina virtual, pero es fácil adaptar el código de una pregunta similar sobre bytes en 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();
    }
}

Para reiterar, esto depende de la VM, pero en mi computadora portátil con Windows que ejecuta Sun's JDK build 1.6.0_11 obtuve los siguientes resultados:

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

Eso sugiere que los valores booleanos se pueden empaquetar básicamente en un byte cada uno mediante la JVM de Sun.

Jon Skeet
fuente
21
@skeet - Realmente te saludo. Tu respuesta es increíble
Warrior
2
@warrior: Como ya tenía el código para "byte", cambiarlo a "booleano" fue bastante sencillo :)
Jon Skeet
3
System.gc () no garantiza la limpieza de la memoria. Simplemente le da una orden a la JVM para que ejecute la recolección de basura, pero no significa que el recolector realmente limpió algo. Recuerde que el coleccionista limpia los objetos NO UTILIZADOS. Un objeto no se utiliza si el programa no tiene más referencias a él. Entonces, en su prueba, eliminaría explícitamente la referencia configurando LotsOfBooleans en nulo antes de ejecutar gc (); O simplemente ejecute main una vez con boolean, una vez con int y luego compare los números.
Randa Sbeity
2
@RandaSbeity O incluso mejor: asegúrese de conservar ambas referencias y calcular la diferencia de memoria. Que es exactamente lo que pasa aquí.
biziclop
1
¿Hay alguna pregunta que Jon Skeet no pueda responder?
Andreas Hartmann
31

La información real representada por un valor booleano en Java es un bit: 1 para verdadero, 0 para falso. Sin embargo, el tamaño real de una variable booleana en la memoria no está definido con precisión por la especificación de Java. Consulte Tipos de datos primitivos en Java .

El tipo de datos booleano solo tiene dos valores posibles: verdadero y falso. Utilice este tipo de datos para indicadores simples que rastrean condiciones verdaderas / falsas. Este tipo de datos representa un bit de información, pero su "tamaño" no es algo que esté definido con precisión.

William Brendel
fuente
21

En otros comentarios...

Si está pensando en utilizar una matriz de objetos booleanos, no lo haga. En su lugar, utilice un BitSet: tiene algunas optimizaciones de rendimiento (y algunos métodos extra agradables que le permiten obtener el siguiente bit activado / desactivado).

Matthew Schinckel
fuente
Esto no siempre es cierto stackoverflow.com/questions/605226/…
Przemek
Esa respuesta sugiere que hay razones importantes para usar boolean [], pero como indican los comentarios allí, no hay mucho que respalde. Habiendo dicho eso: no
programo
6

Leí que Java reserva un byte para un booleantipo de datos, pero usa solo un bit. Sin embargo, la documentación dice que "su" tamaño "no es algo que esté definido con precisión" . Mira aquí.

JavaNewbie_M107
fuente
Eso es un tutorial, no 'la documentación'. La documentación es JLS, JVM Spec. Y Javadoc.
Marqués de Lorne
2

Los booleanvalores se compilan en intel tipo de datos en JVM. Vea aquí .

rics
fuente
2
No es necesariamente así como se almacenan en la memoria, y creo que eso es lo que la persona que hace la pregunta quería saber. Ese documento describe el formato de archivo de clase (código de bytes compilado), no la representación de una variable booleana en la memoria, porque eso depende de la implementación.
William Brendel
2

El tamaño del booleano en Java depende de la máquina virtual. pero cualquier objeto Java está alineado con una granularidad de 8 bytes. Un booleano tiene 8 bytes de encabezado, más 1 byte de carga útil, para un total de 9 bytes de información. La JVM luego lo redondea al siguiente múltiplo de 8. por lo que la única instancia de java.lang.Boolean ocupa 16 bytes de memoria.

Deepak Odedara
fuente
Tiendo a no estar de acuerdo, en HotSpot JVM 1.7.0_51 el encabezado tiene 12 bytes + 1 para el booleano + 3 para la granularidad.
Eugene
14
no confunda booleano con booleano.
andresp
1
Bytes o bits? 16 bytes para un mundo Booleansería un desperdicio ... ese es el tamaño de un longque puede transportar un billón de veces más información que unBoolean
Dici
0

No está definido; Hacer cosas como las que sugirió Jon Skeet le dará una aproximación en una plataforma determinada, pero la forma de saberlo con precisión para una plataforma específica es usar un generador de perfiles.

Lawrence Dol
fuente