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 sizeof
operador: 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.