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

7

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

  

no definido con precisión

Explicación adicional dice

  

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

La pregunta que me vino a la mente fue ¿por qué el 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 enlace donde dice

  

la JVM usa una celda de pila de 32 bits, utilizada para mantener variables locales, método   Argumentos y valores de expresión. Primitivas que son más pequeñas que 1   Las celdas se rellenan, primitivas mayores de 32 bits (largo y doble)   tomar 2 celdas

¿Significa que incluso los tipos de datos de byte / char / short primitiva 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 la CPU de 32 bits y de 64 bits en la CPU de 64 bits?

    
pregunta user3222249 02.01.2018 - 17:45

2 respuestas

9

TL; DR Lo único seguro es que boolean ocupa 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 idioma ). Por lo tanto, no solo el tamaño boolean no está definido en este nivel. Y boolean tiene dos valores posibles: false y true .

La Especificación de la máquina virtual dice En este caso, las variables boolean se tratan como int con los valores 0 y 1. Solo las matrices de boolean tienen soporte específico. Entonces, a nivel de Máquina Virtual, una variable boolean ocupa la misma cantidad de espacio que 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 bytes JVM en un código de máquina optimizado específico de la CPU, y apuesto a que en muchos casos es capaz de deducir el rango de valores limitado de int -masked boolean del contexto y usa un tamaño más pequeño.

    
respondido por el Ralf Kleberhoff 02.01.2018 - 21:23
7

Hay una serie de conceptos para separar:

  • el propio lenguaje de programación Java, que es un lenguaje de programación textual,
  • el código de bytes de la máquina virtual Java & formato de archivo de clase , que es una codificación compilada en binario del código fuente original del lenguaje Java, y se usa como un formato de archivo de intercambio para almacenar, cargar y compartir el código objeto de java,
  • una implementación particular de la Máquina Virtual Java , que podría ser un intérprete, aunque a menudo es una implementación basada en JIT,
  • El código de máquina generado por JIT 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 un operador sizeof : 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, el lenguaje Java sí 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 indagar sobre el tamaño de un objeto, pero (1) esto requiere instrumentación, (2) proporciona solo una estimación, y (3) esta indagación no se aplica a primitivos tipos o variables locales.

  
    

la JVM usa una celda de pila de 32 bits, utilizada 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 (largo y doble) 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 la implementación de 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 restringe a la discusión de variables / parámetros / expresiones locales que normalmente se asignan a la pila (por ejemplo, automática o automática en C / C ++), y no analiza 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 en ocasiones el manejo de 8 bits requiere una o dos instrucciones adicionales 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 sujetos a problemas de escalamiento, en particular, en comparación con los objetos y matrices, que son utilizados por las estructuras de datos de potencialmente cualquier escala.

(Podríamos considerar la recursión como una escala de las variables locales, por lo que una mayor cantidad de variables locales en las rutinas recursivas corre el riesgo de desbordarse de la pila antes).

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

  

¿Significa que incluso los tipos de datos de byte / char / short primitiva 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 objetos, dentro del código de bytes JVM & mecanismo de archivo de clase, los campos son directamente accesibles por su identificación y no hay una noción dada de "celdas", mientras que existe con las variables (locales y de parámetros).

Una implementación de 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), por lo que dos campos de 16 bits pueden ocupar la misma palabra de 32 bits, incluso si no se declararon de manera adyacente el código fuente; esto reduce la sobrecarga causada por el relleno requerido para mantener la alineación. Cualquiera de estos ajustes de alzado, relleno y campo también son muy específicos de la implementación de la JVM en lugar de las preocupaciones del formato de intercambio de la JVM. En teoría, el JIT podría empaquetar booleanos hasta un bit en una matriz, o empaquetar 8 campos booleanos individuales en un solo byte en un objeto. Que la mayoría no lo hace es una elección de implementación JVM.

    
respondido por el Erik Eidt 02.01.2018 - 23:34

Lea otras preguntas en las etiquetas