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

La spécification Java Virtual Machine indique que la prise en charge des types primitifs booléens est limitée.

Il n’y a pas d’instructions de machine virtuelle Java 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 des valeurs booléennes sont compilées pour utiliser les valeurs du type de données Java virtual machine int.

Ce qui précède implique (bien que je puisse l’avoir mal interprété) que le type de données int est utilisé lors d’opérations sur booléens, mais il s’agit d’une construction de mémoire de 32 bits. Étant donné qu’un booléen ne représente que 1 bit d’information:

  • Pourquoi un octet ou un type court n’est-il pas utilisé comme proxy pour un booléen au lieu de int?
  • Pour une JVM donnée, quel est le moyen le plus fiable de savoir exactement combien de mémoire est utilisée pour stocker un type booléen?

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

Réponse plus longue: la machine virtuelle Java utilise une stack de 32 bits, utilisée pour contenir des variables locales, des arguments de méthode et des 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 de codes d’opération, mais a certains effets secondaires particuliers (comme la nécessité de masquer les octets).

Les primitives stockées dans les tableaux peuvent utiliser moins de 32 bits, et il existe différents codes d’opération pour charger et stocker les valeurs primitives d’un tableau. Les valeurs booléennes et en octets utilisent toutes les 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 objects en mémoire, celle-ci est couverte par les règles “implémentation privée”, elle peut être de 1 bit, 1 octet ou, comme l’a montré une autre affiche, sur une limite de double mot de 64 bits. Très probablement, il prend la taille de mot de base du matériel sous-jacent (32 ou 64 bits).


En ce qui concerne la réduction de la quantité d’espace utilisée, ce n’est pas un problème pour la plupart des applications. Les frameworks de stack (contenant des variables locales et des arguments de méthode) ne sont pas très volumineux et, dans le grand schéma, un booléen discret dans un object n’est pas très grand non plus. Si vous avez beaucoup d’objects avec beaucoup de booléens, vous pouvez utiliser des champs de bits gérés via vos getters et setters. Cependant, vous payez une pénalité en temps CPU qui est probablement supérieure à la pénalité en mémoire.

Un seul booléen quelque part dans la hiérarchie d’inheritance peut utiliser jusqu’à 8 octets! Ceci est dû au remplissage. Plus de détails peuvent être trouvés dans Quelle quantité de mémoire est utilisée par mon object Java? :

Pour revenir à la question de la consommation d’un booléen, oui, il consum au moins un octet, mais en raison des règles d’alignement, il peut consumr beaucoup plus. À mon humble avis, il est plus intéressant de savoir qu’un booléen [] consumra 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 de graphe où de grands champs de bits sont utiles, et vous devez savoir que si vous utilisez un booléen, vous aurez besoin de exactement 8 fois plus de mémoire que nécessaire (1 octet contre 1 bit).

La 5ème édition de Java in a Nutshell (O’Reilly) dit qu’un type primitif booléen est de 1 octet. Cela pourrait être faux, selon ce que montre l’examen du tas. Je me demande si la plupart des machines virtuelles Java ont des problèmes d’allocation de moins d’un octet pour les variables.

La cartographie booléenne a été réalisée avec un processeur 32 bits en tête. La valeur int a 32 bits pour pouvoir être traitée en une seule opération.

Voici une solution du Java IAQ de Peter Norvig: Questions à réponses 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."); 

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 processeur puisse le traiter. Cela ne prend pas beaucoup de temps, mais si vous avez besoin de 2 cycles de processeur au lieu de 1 pour les opérations de base, cela signifie que les coûts / temps ont doublé.

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 choisi la vitesse.

Boolean représente un bit d’information, mais sa “taille” n’est pas définie avec précision, par exemple les tutoriels Sun Java. Les littéraux booléens n’ont que deux valeurs possibles: ils sont vrais et faux. Voir Types de données Java pour plus de détails.

Pourquoi ne pas créer un fichier .java comme celui-ci:

Vide.java

 class Empty{ } 

et une classe comme celle-ci:

NotEmpty.java

 class NotEmpty{ boolean b; } 

Comstackz-les tous les deux et comparez les fichiers .class avec un éditeur hexadécimal.