tamaño booleano no definido en java: ¿por qué?

10

Veo que el tamaño de booleano no está definido. A continuación hay dos declaraciones que veo en el tamaño de datos primitivos de Java

no definido con precisión

Más explicaciones dice

boolean representa un bit de información, pero su "tamaño" no es algo que esté definido con precisión.

La pregunta que se me ocurrió fue por qué booleano en java no se puede representar con 1 bit (o 1 byte si el byte es la representación mínima).

Pero veo que ya se ha respondido en /programming/1907318/why-is-javas-boolean-primitive-size-not-defined donde dice

la JVM usa una celda de pila de 32 bits, usada 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 más grandes que 32 bits (largas y dobles) toman 2 celdas

¿Significa que incluso los tipos de datos primitivos byte / char / short también toman 32 bits aunque su tamaño se define como 8/16/16 bit?

¿También podemos decir que el tamaño booleano será de 32 bits en una CPU de 32 bits y 64 bits en una CPU de 64 bits?

usuario3222249
fuente
Does it mean even byte/char/short primitiva data types also take 32 bit though their size is defined as 8/16/16 bit ?-- Si.
Robert Harvey
Also can we say boolean size will be 32 bit on 32 bit cpu and 64 bit on 64 bit cpu ?- No. El tamaño lo define la JVM.
Robert Harvey
@RobertHarvey Si los tipos de datos byte / char / short primitivee también toman 32 bits, ¿cuál es el punto de definir su tamaño como 8/16/16 bit en Java?
user3222249
Para que puedan almacenarse de manera más eficiente en matrices.
Robert Harvey

Respuestas:

11

TL; DR Lo único seguro es que booleanocupa al menos un bit. Todo lo demás depende de la implementación de JVM.

La especificación del lenguaje Java no define tamaños, solo rangos de valores (consulte La especificación del lenguaje ). Por lo tanto, no solo el booleantamaño es indefinido en este nivel. Y booleantiene dos valores posibles: falsey true.

La especificación de máquina virtual nos dice que las booleanvariables se tratan como intcon valores 0 y 1. Solo las matrices booleantienen soporte específico. Entonces, en el nivel de máquina virtual, una booleanvariable ocupa la misma cantidad de espacio que una int, lo que significa una celda de pila: al menos 4 bytes, típicamente 4 bytes en Java de 32 bits y 8 bytes en 64 bits.

Finalmente, está el motor HotSpot que compila el código de intbytes JVM en un código de máquina optimizado específico para la CPU, y apuesto a que en muchos casos es capaz de deducir el rango de valor limitado de una máscara booleandel contexto y usar un tamaño más pequeño.

Ralf Kleberhoff
fuente
Como Robert y usted también dijeron indirectamente que si los tipos de datos primitivos byte / char / short también toman 32 bits, mi pregunta es ¿cuál es el punto de definir su tamaño como 8/16/16 bit en Java?
user3222249
El punto de definir su rango de valor limitado (o "tamaño", si lo prefiere) es su semántica, por ejemplo, envolviendo de 127 a -128. A menudo no es deseado, pero a veces es útil. Y luego hay matrices de los tipos más cortos, y realmente ocupan menos espacio que las matrices int. Y finalmente existe el potencial del compilador JIT / motor HotSpot de optimizar el espacio a menos de 4 bytes.
Ralf Kleberhoff
8

Hay una serie de conceptos para separar:

  • el lenguaje de programación Java en sí, que es un lenguaje de programación textual,
  • el formato de archivo de clase y código de bytes de la máquina virtual Java , que es una codificación compilada binaria del código fuente del lenguaje Java original, y se utiliza como formato de archivo de intercambio para almacenar, cargar y compartir código de objeto Java,
  • una implementación particular de Java Virtual Machine , que podría ser un intérprete, aunque a menudo es una implementación basada en JIT,
  • JIT generó código de máquina que se ejecuta directamente en el procesador de hardware.

Java, el lenguaje de programación , no define un tamaño de concepto de tipos primitivos porque (a diferencia de C / C ++) no hay sizeofoperador: los tamaños no son observables a través de construcciones de lenguaje, por lo que el lenguaje no necesita definirlos.

Como @Ralf señala que el lenguaje Java define el rango de los tipos primitivos, lo cual es muy relevante para el programador ya que estos rangos se pueden observar a través de construcciones dentro del lenguaje.

El lenguaje define una capacidad de instrumentación que permite la investigación del tamaño de un objeto, pero (1) esto requiere instrumentación, (2) proporciona solo una estimación y (3) esta consulta no se aplica a tipos primitivos o variables locales.

la JVM usa una celda de pila de 32 bits, usada 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 más grandes que 32 bits (largas y dobles) toman 2 celdas

La cita de relleno habla de los detalles del formato de archivo de clase JVM, que se está utilizando como un mecanismo de intercambio (a diferencia del lenguaje Java y una implementación JVM). Aunque lo que dice es válido para la máquina abstracta y el código de bytes JVM, no necesariamente tiene que ser válido para el código de máquina JIT.

La cita de relleno también se limita a la discusión de variables / parámetros / expresiones locales que generalmente se asignan por pila (por ejemplo, automático o automático en C / C ++), y no discute objetos / matrices.

El tamaño real de tales variables automáticas casi nunca es un problema (por ejemplo, para el rendimiento o para el espacio).

En parte, esto se debe a que las CPU de hardware subyacentes funcionan de forma más natural en tamaños de bits más grandes (como 32 o 64) en lugar de 1 bit. Incluso los tamaños de 8 o 16 bits generalmente no son más rápidos que 32, y a veces el manejo de 8 bits requiere una instrucción adicional o dos para trabajar con los registros más amplios del conjunto de instrucciones de hardware.

Y otra razón es el uso limitado de variables locales: se usan directamente por código y solo por código, y por lo tanto no están realmente sujetas a problemas de escala, en particular, en comparación con objetos y matrices, que son utilizados por estructuras de datos de cualquier escala .

(Podríamos considerar la recursividad como una escala de las variables locales, por lo que las variables locales más grandes en las rutinas recursivas arriesgan el desbordamiento de la pila antes).

Sin embargo, los tamaños de los objetos pueden ser muy importantes, si el recuento de instancias es alto, y también, los tamaños de los elementos de la matriz pueden ser importantes si tienen un gran número de elementos.


¿Significa que incluso los tipos de datos primitivos byte / char / short también toman 32 bits aunque su tamaño se define como 8/16/16 bit?

Para los locales, tal vez, tal vez no dependiendo del JIT.

Para los objetos, dentro del mecanismo de código de bytes JVM y archivo de clase, los campos tienen acceso directo mediante su identificación y no se da una noción de "celdas", mientras que sí existe con las variables (local y de parámetros).

Una implementación JVM (incluido su JIT) tiene la flexibilidad de reorganizar el orden de los campos dentro de la implementación (por ejemplo, a nivel de código de máquina) para que dos campos de 16 bits puedan ocupar la misma palabra de 32 bits incluso si no se declararon adyacentes en el código fuente ; Esto reduce la sobrecarga causada por el relleno requerido para mantener la alineación. Cualquier alusión, relleno y ubicación de campo también son muy específicos de la implementación de JVM en lugar de las preocupaciones del formato de intercambio de JVM. En teoría, el JIT podría empaquetar booleanos hasta un bit en una matriz, o empacar 8 campos booleanos individuales en un solo byte en un objeto. Lo que más no es una opción de implementación de JVM.

Erik Eidt
fuente