web-dev-qa-db-fra.com

taille booléenne non définie en Java: pourquoi?

Je vois que la taille du booléen n'est pas définie. Voici deux déclarations que je vois à taille des données primitives Java

pas précisément défini

Une explication supplémentaire dit

booléen représente un bit d'information, mais sa "taille" n'est pas quelque chose qui est précisément défini.

La question m'est venue à l'esprit: pourquoi booléen en Java ne peut pas être représenté avec 1 bit (ou 1 octet si l'octet est la représentation minimale)?

Mais je vois qu'il a déjà été répondu à https://stackoverflow.com/questions/1907318/why-is-javas-boolean-primitive-size-not-defined où il est dit

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

Cela signifie-t-il que même les types de données primitiva byte/char/short prennent également 32 bits bien que leur taille soit définie comme 8/16/16 bits?

Peut-on également dire que la taille booléenne sera de 32 bits sur un processeur 32 bits et de 64 bits sur un processeur 64 bits?

9
user3222249

TL; DR La seule chose sûre est que boolean occupe au moins un bit. Tout le reste dépend de l'implémentation JVM.

La spécification de langage Java Language ne définit pas de tailles, uniquement des plages de valeurs (voir The Language Spec ). Ainsi, ce n'est pas seulement la taille boolean qui est non défini à ce niveau. Et boolean a deux valeurs possibles: false et true.

Virtual Machine Specification nous indique que les variables boolean sont traitées comme int avec les valeurs 0 et 1. Seuls les tableaux de boolean ont un support spécifique. Ainsi, au niveau de la machine virtuelle, une variable boolean occupe la même quantité d'espace qu'une int, ce qui signifie une cellule de pile: au moins 4 octets, généralement 4 octets sur 32 bits Java et 8 octets sur 64 bits.

Enfin, il y a le moteur HotSpot qui compile le bytecode JVM en code machine optimisé spécifique au CPU, et je parie que dans de nombreux cas, il est capable de déduire la plage de valeurs limitée d'un int- masqué boolean de le contexte et utiliser une taille plus petite.

10
Ralf Kleberhoff

Il y a un certain nombre de concepts à démêler:

  • le langage de programmation Java lui-même, qui est un langage de programmation textuel,
  • le Java octet-code de la machine virtuelle & format de fichier de classe, qui est un encodage binaire compilé du Java, et est utilisé comme format de fichier d'échange pour stocker, charger et partager Java code objet,
  • une machine virtuelle Java Virtual Machine implementation, qui pourrait être un interpréteur bien que ce soit souvent une implémentation basée sur JIT,
  • Code machine généré par JIT qui s'exécute directement sur le processeur matériel.

Java, le langage de programmation, ne définit pas la taille d'un concept de types primitifs car (contrairement à C/C++) il n'y a pas d'opérateur sizeof: les tailles ne sont pas observables via les constructions de langage, donc le langage n'a pas besoin de les définir.

Comme @Ralf le fait remarquer, le langage Java définit la plage des types primitifs, ce qui est très pertinent pour le programmeur car ces plages peuvent être observées via des constructions dans le langage.

Le langage définit une capacité d'instrumentation qui permet une enquête sur la taille d'un objet, mais (1) cela nécessite une instrumentation, (2) ne fournit qu'une estimation et (3) cette enquête ne s'applique pas aux types primitifs ou variables locales.

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 complétées, les primitives supérieures à 32 bits (longues et doubles) prennent 2 cellules

La citation de remplissage parle des détails du format de fichier de classe JVM, qui est utilisé comme mécanisme d'échange (différent du Java et implémentation JVM). Bien que ce qu'il dit soit valable pour le machine abstraite et code d'octet JVM, il ne doit pas nécessairement tenir pour le code machine JIT.

La citation de remplissage se limite également à la discussion des variables/paramètres/expressions locaux qui sont généralement alloués à la pile (par exemple, auto ou automatique en C/C++), et ne traite pas des objets/tableaux.

La taille réelle de ces variables automatiques n'est presque jamais un problème (par exemple pour les performances ou pour l'espace).

Cela est en partie dû au fait que les processeurs matériels sous-jacents fonctionnent plus naturellement sur des tailles de bits plus grandes (comme 32 ou 64) plutôt que sur 1 bit. Même les tailles 8 ou 16 bits ne sont généralement pas plus rapides que 32, et la gestion 8 bits nécessite parfois une ou deux instructions supplémentaires pour fonctionner avec les registres plus larges du jeu d'instructions matérielles.

Et une autre raison est l'utilisation limitée des variables locales - elles sont utilisées directement par le code et uniquement par le code, et donc pas vraiment sujettes à des problèmes de mise à l'échelle - en particulier, par rapport aux objets et aux tableaux, qui sont utilisés par des structures de données de n'importe quelle échelle. .

(Nous pourrions considérer la récursivité comme une mise à l'échelle des variables locales, donc une plus grande variable locale dans les routines récursives risque de déborder la pile plus tôt.)

Cependant, la taille des objets peut être très importante si le nombre d'instances est élevé, et la taille des éléments du tableau peut également avoir de l'importance si le nombre d'éléments est élevé.


Cela signifie-t-il que même les types de données primitiva byte/char/short prennent également 32 bits bien que leur taille soit définie comme 8/16/16 bits?

Pour les locaux, peut-être, peut-être pas en fonction du JIT.

Pour les objets, dans le mécanisme de code d'octet et de fichier de classe JVM, les champs sont directement accessibles par leur identification et aucune notion n'est donnée de "cellules" - alors qu'il y en a avec les variables (locales et paramètres).

Une implémentation JVM (y compris son JIT) a la flexibilité de réorganiser l'ordre des champs au sein de l'implémentation (par exemple au niveau du code machine) afin que deux champs 16 bits puissent occuper le même mot 32 bits même s'ils n'ont pas été déclarés adjacents dans le code source ; cela réduit les frais généraux causés par le rembourrage nécessaire pour maintenir l'alignement. De tels alighment, padding et field placement sont également très spécifiques à l'implémentation JVM plutôt que des problèmes de format d'échange JVM. En théorie, le JIT pourrait regrouper les booléens jusqu'à un bit dans un tableau, ou regrouper 8 champs booléens individuels en un seul octet dans un objet. Ce que la plupart ne font pas est un choix d'implémentation JVM.

8
Erik Eidt