¿Por qué el tamaño de la primitiva booleana de Java no está definido?

La Especificación de Máquina Virtual Java dice que hay soporte limitado para tipos primitivos booleanos.

No hay instrucciones de la máquina virtual Java únicamente dedicadas a operaciones en valores booleanos. En cambio, las expresiones en el lenguaje de progtwigción Java que operan en valores booleanos se comstackn para usar valores del tipo de datos int de la máquina virtual Java.

Lo anterior implica (aunque puedo haberlo malinterpretado) que el tipo de datos int se usa cuando se trabaja en booleanos, pero esta es una construcción de memoria de 32 bits. Dado que un booleano solo representa 1 bit de información:

  • ¿Por qué no se usa un byte o tipo corto como proxy para un booleano en lugar de int?
  • Para cualquier JVM dada, ¿cuál es la forma más confiable de averiguar exactamente cuánta memoria se usa para almacenar un tipo booleano?

Respuesta corta: sí, los valores booleanos se manipulan como entidades de 32 bits, pero las matrices de booleanos usan 1 byte por elemento.

Respuesta más larga: la JVM usa una celda de stack de 32 bits, que se usa para contener variables locales, argumentos de métodos y valores de expresión. Las primitivas que son más pequeñas que 1 celda se rellenan, las primitivas de más de 32 bits (largo y doble) toman 2 celdas. Esta técnica minimiza el número de códigos de operación, pero tiene algunos efectos secundarios peculiares (como la necesidad de enmascarar bytes).

Las primitivas almacenadas en matrices pueden usar menos de 32 bits, y existen diferentes códigos de operación para cargar y almacenar valores primitivos de una matriz. Los valores booleanos y de byte usan los códigos de operación baload y bastore, lo que implica que las matrices booleanas toman 1 byte por elemento.

En lo que respecta al diseño de objetos en memoria, esto está cubierto por las reglas de “implementación privada”, puede ser de 1 bit, 1 byte o como otro cartel anotado, alineado con un límite de doble palabra de 64 bits. Lo más probable es que tome el tamaño de palabra básico del hardware subyacente (32 o 64 bits).


En cuanto a minimizar la cantidad de espacio que usan los booleanos: realmente no es un problema para la mayoría de las aplicaciones. Los marcos de stack (que contienen variables locales y argumentos de método) no son muy grandes, y en el esquema grande, un booleano discreto en un objeto tampoco es tan grande. Si tiene muchos objetos con muchos booleanos, puede usar campos de bits que se administran a través de sus getters y setters. Sin embargo, pagará una penalización en tiempo de CPU que probablemente sea mayor que la penalización en memoria.

¡Un único booleano en algún lugar de la jerarquía de herencia puede usar hasta 8 bytes! Esto se debe al relleno. Se pueden encontrar más detalles en ¿Cuánta memoria usa mi objeto Java? :

Volviendo a la pregunta de cuánto consume un booleano, sí consume al menos un byte, pero debido a las reglas de alineación puede consumir mucho más. En mi humilde opinión, es más interesante saber que un booleano [] consumirá un byte por entrada y no un bit, más algunos gastos indirectos debido a la alineación y para el campo de tamaño de la matriz. Hay algoritmos de gráficos en los que grandes campos de bits son útiles, y debe tener en cuenta que, si utiliza un booleano [], necesita casi exactamente 8 veces más memoria de la que realmente necesita (1 byte frente a 1 bit).

La quinta edición de Java in a Nutshell (O’Reilly) dice que un tipo primitivo booleano es de 1 byte. Eso podría estar mal, según lo que muestra el examen del montón. Me pregunto si la mayoría de las JVM tienen problemas para asignar menos de un byte a las variables.

El mapeo booleano se hizo con una CPU de 32 bits en mente. El valor int tiene 32 bits, por lo que se puede procesar en una sola operación.

Aquí hay una solución de Java IAQ de Peter Norvig: Preguntas poco frecuentes para medir el tamaño (con alguna imprecisión):

static Runtime runtime = Runtime.getRuntime(); ... long start, end; Object obj; runtime.gc(); start = runtime.freememory(); obj = new Object(); // Or whatever you want to look at end = runtime.freememory(); System.out.println("That took " + (start-end) + " bytes."); 

Las CPU operan en un tipo de datos específico de longitud. En el caso de las CPU de 32 bits, tienen una longitud de 32 bits y, por lo tanto, lo que usted llama ‘int’ en Java. Todo lo que se encuentre debajo o encima debe llenarse o dividirse a esta longitud antes de que la CPU pueda procesarlo. Esto no lleva mucho tiempo, pero si necesita 2 ciclos de CPU en lugar de 1 para las operaciones básicas, esto significa costos / tiempos duplicados.

Esta especificación está dedicada a las CPU de 32 bits para que puedan procesar booleanos con su tipo de datos nativo.

Aquí solo puede tener uno: velocidad o memoria: SUN se decidió por la velocidad.

Boolean representa un bit de información, pero su “tamaño” no es algo que se defina con precisión, digamos los tutoriales de Sun Java. Los literales booleanos solo tienen dos valores posibles, los verdaderos y los falsos. Ver Tipos de datos de Java para más detalles.

¿Por qué no hacer un archivo .java como este?

Empty.java

 class Empty{ } 

y una clase como esta:

NotEmpty.java

 class NotEmpty{ boolean b; } 

Comstackr ambos y comparar los archivos .class con un editor hexadecimal.