tamanho booleano não definido em java: por quê?

10

Eu vejo o tamanho do booleano não está definido. Abaixo estão duas instruções que vejo no tamanho dos dados primitivos em java

não definido com precisão

Mais explicações dizem

booleano representa um pouco de informação, mas seu "tamanho" não é algo definido com precisão.

A pergunta que veio à minha mente foi por que o booleano em java não pode ser representado com 1 bit (ou 1 byte se byte for uma representação mínima)?

Mas vejo que já foi respondido em /programming/1907318/why-is-javas-boolean-primitive-size-not-defined onde diz

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

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?

Também podemos dizer que o tamanho booleano será de 32 bits na CPU de 32 bits e de 64 bits na CPU de 64 bits?

user3222249
fonte
Does it mean even byte/char/short primitiva data types also take 32 bit though their size is defined as 8/16/16 bit ?-- Sim.
Robert Harvey
Also can we say boolean size will be 32 bit on 32 bit cpu and 64 bit on 64 bit cpu ?- Não. O tamanho é definido pela JVM.
Robert Harvey
@RobertHarvey Se os tipos de dados byte / char / short primitivo também levam 32 bits, qual é o sentido de definir seu tamanho como 8/16/16 bits em java?
user3222249
Para que eles possam ser armazenados com mais eficiência em matrizes.
Robert Harvey

Respostas:

11

TL; DR A única coisa certa é que booleanocupa pelo menos um bit. Tudo o resto depende da implementação da JVM.

A Java Language Specification não define tamanhos, apenas intervalos de valores (consulte The Language Spec ). Portanto, não é apenas o booleantamanho indefinido neste nível. E booleantem dois valores possíveis: falsee true.

A Especificação de máquina virtual nos diz que as booleanvariáveis ​​são tratadas como intcom os valores 0 e 1. Somente matrizes booleanpossuem suporte específico. Portanto, no nível da Máquina Virtual, uma booleanvariável ocupa a mesma quantidade de espaço que uma int, ou seja, uma célula da pilha: pelo menos 4 bytes, normalmente 4 bytes em Java de 32 bits e 8 bytes em 64 bits.

Finalmente, há o mecanismo HotSpot que compila o bytecode da JVM em código de máquina específico da CPU otimizado, e aposto que, em muitos casos, é capaz de deduzir o intervalo limitado de valores de um intmascarado booleando contexto e usar um tamanho menor.

Ralf Kleberhoff
fonte
Como Robert e você também disseram indiretamente que, se os tipos de dados primitivos byte / char / short também levam 32 bits, minha pergunta é: qual é o sentido de definir seu tamanho como 16/16/16 bits em java?
precisa saber é o seguinte
O ponto de definir seu intervalo de valor limitado (ou "tamanho", se você preferir) é a semântica, por exemplo, agrupando de 127 a -128. Muitas vezes isso é indesejável, mas às vezes útil. E existem matrizes dos tipos mais curtos e elas realmente ocupam menos espaço do que matrizes int. E, finalmente, há o potencial do compilador JIT / mecanismo HotSpot de otimizar o espaço para menos de 4 bytes.
Ralf Kleberhoff
8

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á sizeofoperador: 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.

Erik Eidt
fonte