Há vários conceitos a serem destacados:
- a própria linguagem de programação Java, que é uma linguagem de programação textual,
- o código de byte e o formato de arquivo de classe da Java Virtual Machine , que é uma codificação binária compilada do código-fonte original da linguagem Java e é usada como um formato de arquivo de intercâmbio para armazenar, carregar e compartilhar código de objeto java,
- uma implementação específica da Java Virtual Machine , que poderia ser um intérprete, embora geralmente seja uma implementação baseada em JIT,
- O JIT gerou um código de máquina que é executado diretamente no processador de hardware.
Java, a linguagem de programação , não define um tamanho de conceito de tipos primitivos porque (ao contrário de C / C ++) não há sizeof
operador: os tamanhos não são observáveis por meio de construções de linguagem, portanto a linguagem não precisa defini-los.
Como o @Ralf aponta, a linguagem Java define o intervalo dos tipos primitivos, o que é muito relevante para o programador, pois esses intervalos podem ser observados por meio de construções na linguagem.
A linguagem define um recurso de instrumentação que permite a investigação do tamanho de um objeto, mas (1) isso requer instrumentação, (2) fornece apenas uma estimativa e (3) essa investigação não se aplica a tipos primitivos ou variáveis locais.
a JVM usa uma célula de pilha de 32 bits, usada para armazenar variáveis locais, argumentos de método e valores de expressão. Primitivas menores que 1 célula são preenchidas, primitivas maiores que 32 bits (longas e duplas) levam 2 células
A cotação de preenchimento fala dos detalhes do formato do arquivo de classe da JVM, que está sendo usado como um mecanismo de intercâmbio (diferente da linguagem Java e da implementação da JVM). Embora o que diz seja válido para a máquina abstrata e o código de bytes da JVM, ele não precisa necessariamente ser válido para o código da máquina com JIT.
A citação de preenchimento também se restringe à discussão de variáveis / parâmetros / expressões locais que normalmente são alocados à pilha (por exemplo, automático ou automático em C / C ++) e não discute objetos / matrizes.
O tamanho real dessas variáveis automáticas quase nunca é um problema (por exemplo, para desempenho ou espaço).
Em parte, isso ocorre porque as CPUs de hardware subjacentes funcionam mais naturalmente em tamanhos de bits maiores (como 32 ou 64) em vez de 1 bit. Mesmo tamanhos de 8 ou 16 bits geralmente não são mais rápidos que 32 e, às vezes, o processamento de 8 bits requer uma instrução extra ou duas para trabalhar com os registros mais amplos do conjunto de instruções de hardware.
E outro motivo é o uso limitado de variáveis locais - elas são usadas diretamente pelo código e somente pelo código e, portanto, não estão realmente sujeitas a problemas de dimensionamento - em particular, em comparação com objetos e matrizes, que são usados por estruturas de dados de qualquer escala potencialmente .
(Podemos considerar a recursão como dimensionamento de variáveis locais, portanto, variáveis locais maiores em rotinas recursivas arriscam o estouro da pilha mais cedo.)
No entanto, os tamanhos dos objetos podem ser muito importantes, se a contagem de instâncias for alta e também o tamanho dos elementos da matriz, se houver um número alto de elementos.
Isso significa que mesmo os tipos de dados byte / char / short primitiva também levam 32 bits, embora seu tamanho seja definido como 16/16/16 bits?
Para os locais, talvez, talvez não dependendo do JIT.
Para objetos, no código de byte da JVM e no mecanismo de arquivo de classe, os campos são acessados diretamente por sua identificação e não há noção de "células" - enquanto as variáveis (local e parâmetro) são fornecidas.
Uma implementação da JVM (incluindo sua JIT) tem a flexibilidade de reorganizar a ordem dos campos na implementação (por exemplo, no nível do código da máquina) para que dois campos de 16 bits possam ocupar a mesma palavra de 32 bits, mesmo que não tenham sido declarados adjacentemente no código-fonte. ; isso reduz a sobrecarga causada pelo preenchimento necessário para manter o alinhamento. Quaisquer alighment, padding e posicionamento de campo também são muito específicos da implementação da JVM, em vez de preocupações com o formato de intercâmbio da JVM. Em teoria, o JIT poderia empacotar booleanos até um bit em uma matriz ou empacotar 8 campos booleanos individuais em um único byte em um objeto. O que a maioria não faz é uma opção de implementação da JVM.