Por que o tamanho primitivo booleano do Java não está definido?

A especificação Java Virtual Machine diz que há suporte limitado para tipos primitivos booleanos.

Não há instruções de máquina virtual Java exclusivamente dedicadas a operações em valores booleanos. Em vez disso, as expressões na linguagem de programação Java que operam em valores booleanos são compiladas para usar valores do tipo de dados int da máquina virtual Java.

O acima implica (embora eu possa ter interpretado erroneamente) que o tipo de dados int é usado quando operando em booleanos, mas esta é uma construção de memory de 32 bits. Dado que um booleano representa apenas 1 bit de informação:

  • Por que um byte, ou tipo curto, não é usado como proxy para um booleano em vez de int?
  • Para qualquer JVM dada, qual é a maneira mais confiável de descobrir exatamente quanta memory é usada para armazenar um tipo booleano?

Resposta curta: sim, os valores booleanos são manipulados como entidades de 32 bits, mas as matrizes de booleanos usam 1 byte por elemento.

Resposta mais longa: a JVM usa uma célula de pilha de 32 bits, usada para conter variables ​​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) recebem 2 células. Essa técnica minimiza o número de opcodes, mas tem alguns efeitos colaterais peculiares (como a necessidade de mascarar bytes).

Primitivas armazenadas em matrizes podem usar menos de 32 bits e existem diferentes opcodes para carregar e armazenar valores primitivos de um array. Os valores booleanos e de byte usam os opcodes baload e bastore, o que implica que os arrays booleanos recebem 1 byte por elemento.

No que diz respeito ao layout do object na memory, isso é coberto pelas regras de “implementação privada”, pode ser 1 bit, 1 byte ou outro pôster anotado, alinhado a um limite de palavra dupla de 64 bits. Muito provavelmente, leva o tamanho básico da palavra do hardware subjacente (32 ou 64 bits).


Na medida em que minimiza a quantidade de espaço que booleans usam: realmente não é um problema para a maioria das aplicações. Empilhamento de frameworks (mantendo variables ​​locais e argumentos de método) não são muito grandes, e no grande esquema um booleano discreto em um object também não é grande. Se você tiver muitos objects com muitos booleanos, poderá usar campos de bits gerenciados por seus getters e setters. No entanto, você pagará uma penalidade no tempo de CPU que provavelmente é maior que a penalidade na memory.

Um único booleano em algum lugar na hierarquia de inheritance pode usar até 8 bytes! Isso é devido ao preenchimento. Mais detalhes podem ser encontrados em Quanta memory é usada pelo meu object Java? :

Voltando à questão de quanto um booleano consome, sim ele consome pelo menos um byte, mas devido às regras de alinhamento ele pode consumir muito mais. IMHO é mais interessante saber que um booleano [] irá consumir um byte por input e não um bit, mais alguma sobrecarga devido ao alinhamento e para o campo de tamanho do array. Existem algoritmos de grafos onde grandes campos de bits são úteis, e você precisa estar ciente de que, se você usar um booleano [], você precisará de quase exatamente 8 vezes mais memory do que realmente necessário (1 byte versus 1 bit).

A quinta edição do Java in a Nutshell (O’Reilly) diz que um tipo primitivo booleano é de 1 byte. Isso pode estar errado, com base no que o exame do heap está mostrando. Gostaria de saber se a maioria das JVMs tem problemas com alocação de menos de um byte para variables.

O mapeamento booleano foi feito com uma CPU de 32 bits em mente. O valor int tem 32 bits para poder ser processado em uma operação.

Aqui está uma solução de Java IAQ de Peter Norvig: Perguntas respondidas com pouca frequência para medir o tamanho (com alguma imprecisão):

static Runtime runtime = Runtime.getRuntime(); ... long start, end; Object obj; runtime.gc(); start = runtime.freememory(); obj = new Object(); // Or whatever you want to look at end = runtime.freememory(); System.out.println("That took " + (start-end) + " bytes."); 

As CPUs operam em um tamanho de dados específico. No caso de CPUs de 32 bits, elas têm 32 bits e, portanto, o que você chama de ‘int’ em Java. Tudo abaixo ou acima disso deve ser preenchido ou dividido até que a CPU possa processá-lo. Isso não leva muito tempo, mas se você precisar de 2 ciclos de CPU em vez de 1 para operações básicas, isso significa custos / tempo duplicados.

Essa especificação é dedicada para CPUs de 32 bits para que possam processar booleanos com seu tipo de dados nativo.

Você só pode ter um aqui: velocidade ou memory – o SUN decidiu pela velocidade.

O booleano representa um pouco de informação, mas seu “tamanho” não é algo precisamente definido, digamos, os tutoriais do Sun Java. Os literais booleanos têm apenas dois valores possíveis, os que são verdadeiros e falsos. Veja Tipos de Dados Java para detalhes.

Por que não criar um arquivo .java assim:

Empty.java

 class Empty{ } 

e uma class como esta:

NotEmpty.java

 class NotEmpty{ boolean b; } 

Compile os dois e compare os arquivos .class com um editor hexadecimal.