web-dev-qa-db-fra.com

Pourquoi la taille primitive booléenne de Java n'est-elle pas définie?

Le Java Virtual Machine Specification indique que la prise en charge des types booléens primitifs est limitée.

Il n'y a pas Java instructions de machine virtuelle uniquement dédiées aux opérations sur les valeurs booléennes. Au lieu de cela, les expressions du langage de programmation Java qui fonctionnent sur les valeurs booléennes sont compilées pour être utilisées) valeurs du type de données Java machine virtuelle int int.

Ce qui précède implique (même si je l'ai mal interprété) que le type de données int est utilisé lors de l'utilisation de booléens, mais il s'agit d'une construction de mémoire 32 bits. Étant donné qu'un booléen ne représente qu'un bit d'information:

  • Pourquoi un type d'octet ou court n'est-il pas utilisé comme proxy pour un booléen au lieu d'un int?
  • Quelle que soit la machine virtuelle Java, quel est le moyen le plus fiable de savoir exactement combien de mémoire est utilisée pour stocker un type booléen?
107
Joel

Réponse courte: oui, les valeurs booléennes sont manipulées comme des entités 32 bits, mais les tableaux de booléens utilisent 1 octet par élément.

Réponse plus longue: la JVM utilise une cellule de pile 32 bits, utilisée pour contenir les variables locales, les arguments de méthode et les valeurs d'expression. Les primitives inférieures à 1 cellule sont remplies, les primitives supérieures à 32 bits (longues et doubles) prennent 2 cellules. Cette technique minimise le nombre d'opcodes, mais présente certains effets secondaires particuliers (comme la nécessité de masquer les octets).

Les primitives stockées dans des tableaux peuvent utiliser moins de 32 bits, et il existe différents opcodes pour charger et stocker les valeurs primitives à partir d'un tableau. Les valeurs booléennes et d'octets utilisent toutes deux les opcodes baload et bastore, ce qui implique que les tableaux booléens prennent 1 octet par élément.

En ce qui concerne la disposition des objets en mémoire, cela est couvert par la "mise en œuvre privée" règles , il peut être de 1 bit, 1 octet, ou comme une autre affiche l'a noté, aligné sur un double 64 bits - Limite du mot. Très probablement, il prend la taille de base de Word du matériel sous-jacent (32 ou 64 bits).


En ce qui concerne la minimisation de l'espace utilisé par les booléens: ce n'est vraiment pas un problème pour la plupart des applications. Les trames de pile (contenant des variables locales et des arguments de méthode) ne sont pas très grandes, et dans le grand schéma, un booléen discret dans un objet n'est pas si grand non plus. Si vous avez beaucoup d'objets avec beaucoup de booléens, vous pouvez utiliser des champs de bits qui sont gérés via vos getters et setters. Cependant, vous paierez une pénalité en temps CPU qui est probablement plus grande que la pénalité en mémoire.

112
kdgregory

Un seul booléen quelque part dans la hiérarchie d'héritage peut utiliser jusqu'à 8 octets! Cela est dû au rembourrage. Plus de détails peuvent être trouvés dans Combien de mémoire est utilisée par mon Java? :

Revenant à la question de la consommation d'un booléen, oui, il consomme au moins un octet, mais en raison des règles d'alignement, il peut consommer beaucoup plus. À mon humble avis, il est plus intéressant de savoir qu'un booléen [] consommera un octet par entrée et non un bit, plus une surcharge due à l'alignement et au champ de taille du tableau. Il existe des algorithmes graphiques où de grands champs de bits sont utiles, et vous devez être conscient que, si vous utilisez un booléen [], vous avez besoin presque exactement 8 fois plus de mémoire que nécessaire (1 octet contre 1 bit).

7
akuhn

La 5ème édition de Java en bref (O'Reilly) dit qu'un type primitif booléen est de 1 octet. Cela pourrait être faux, d'après ce que montre l'examen du tas. Je me demande si la plupart des JVM ont des problèmes avec l'allocation de moins d'un octet pour les variables.

5
Matthew Flynn

Le mappage booléen a été effectué avec un processeur 32 bits à l'esprit. La valeur int a 32 bits, elle peut donc être traitée en une seule opération.

Voici une solution de Peter Norvig Java IAQ: Questions peu fréquentes pour mesurer la taille (avec une certaine imprécision):

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.");
3
Thomas Jung

Les processeurs fonctionnent sur une longueur de type de données spécifique. Dans le cas des processeurs 32 bits, ils ont une longueur de 32 bits et donc ce que vous appelez "int" en Java. Tout ce qui est en dessous ou au-dessus doit être rempli ou divisé à cette longueur avant que le CPU puisse le traiter. Cela ne prend pas beaucoup de temps, mais si vous avez besoin de 2 cycles CPU au lieu de 1 pour les opérations de base, cela signifie des coûts/temps doublés.

Cette spécification est dédiée aux processeurs 32 bits afin qu'ils puissent traiter les booléens avec leur type de données natif.

Vous ne pouvez en avoir qu'un ici: vitesse ou mémoire - Sun a décidé de la vitesse.

2
Hardcoded

Le booléen représente un bit d'information, mais sa "taille" n'est pas quelque chose qui est précisément défini, par exemple Sun Java. Les littéraux booléens n'ont que deux valeurs possibles: true et false. Voir - Java Data Types pour plus de détails.

1
Krishan