Quelle est la taille d'une variable booléenne en Java?

89

Quelqu'un peut-il dire la taille en bits de booléen en Java?

DonX
la source
1
La même chose est posée ici: stackoverflow.com/questions/1907318/…
dma_k

Réponses:

41

Cela dépend de la machine virtuelle.

guerrier
la source
9
Voulez-vous pointer vers certains documents? J'ai du mal à croire que la taille d'un booléen dépend de la machine. Cela signifierait que la représentation binaire d'une classe contenant un booléen aurait différentes tailles (et dispositions de mémoire) dans différentes VM et cela impliquerait que les VM ne seraient pas compatibles.
David Rodríguez - dribeas
14
Je pense qu'il était implicite que la question se réfère à la taille d'une variable booléenne en mémoire, et non à la taille d'une variable booléenne encodée dans un fichier de classe. La taille de la mémoire varie selon la machine virtuelle selon la documentation de Sun. La taille dans le fichier de classe est constante.
William Brendel
3
@ DavidRodríguez-dribeas - La JVM Sun à l'époque de Java 1.1 utilisait 4 octets pour boolean lorsqu'elle était stockée en tant qu'instance ou var auto. Cela simplifiait la mise en œuvre de l'interpréteur de bytecode (qui considère les booléens comme occupant 4 octets sur la pile) et était le chemin de moindre résistance. Lorsque nous avons implémenté la JVM iSeries "Classic", nous avons trouvé des moyens de rendre les variables d'instance de 1 octet, car cela améliorait considérablement la compacité de certains objets (ce qui a un impact incroyable sur les performances). Apparemment, sur la base des articles ci-dessous, les développeurs de Sun / Oracle ont compris comment faire de même dans les versions ultérieures.
Hot Licks
Mais c'est vrai, à la fin de 2017, les JavaDocs disent: boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined- mais votre point est valide, il pourrait utiliser des liens et de meilleures informations :)
JimLohse
185

Cela dépend de la machine virtuelle, mais il est facile d'adapter le code à partir d'une question similaire concernant les octets en Java :

class LotsOfBooleans
{
    boolean a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    boolean b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    boolean c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    boolean d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    boolean e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}

class LotsOfInts
{
    int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    int c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    int d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    int e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}


public class Test
{
    private static final int SIZE = 1000000;

    public static void main(String[] args) throws Exception
    {        
        LotsOfBooleans[] first = new LotsOfBooleans[SIZE];
        LotsOfInts[] second = new LotsOfInts[SIZE];

        System.gc();
        long startMem = getMemory();

        for (int i=0; i < SIZE; i++)
        {
            first[i] = new LotsOfBooleans();
        }

        System.gc();
        long endMem = getMemory();

        System.out.println ("Size for LotsOfBooleans: " + (endMem-startMem));
        System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));

        System.gc();
        startMem = getMemory();
        for (int i=0; i < SIZE; i++)
        {
            second[i] = new LotsOfInts();
        }
        System.gc();
        endMem = getMemory();

        System.out.println ("Size for LotsOfInts: " + (endMem-startMem));
        System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));

        // Make sure nothing gets collected
        long total = 0;
        for (int i=0; i < SIZE; i++)
        {
            total += (first[i].a0 ? 1 : 0) + second[i].a0;
        }
        System.out.println(total);
    }

    private static long getMemory()
    {
        Runtime runtime = Runtime.getRuntime();
        return runtime.totalMemory() - runtime.freeMemory();
    }
}

Pour réitérer, cela dépend de la VM, mais sur mon ordinateur portable Windows exécutant le JDK build 1.6.0_11 de Sun, j'ai obtenu les résultats suivants:

Size for LotsOfBooleans: 87978576
Average size: 87.978576
Size for LotsOfInts: 328000000
Average size: 328.0

Cela suggère que les booléens peuvent fondamentalement être regroupés dans un octet chacun par la JVM de Sun.

Jon Skeet
la source
21
@skeet - Je vous salue vraiment, votre réponse est géniale
Warrior
2
@warrior: Comme j'avais déjà obtenu le code pour "byte", le changer en "boolean" était assez simple :)
Jon Skeet
3
System.gc () ne garantit pas le nettoyage de la mémoire. Cela donne simplement un ordre à la JVM d'exécuter le ramasse-miettes, mais cela ne signifie pas que le collecteur a réellement nettoyé quelque chose. N'oubliez pas que le collecteur nettoie les objets INUTILISÉS. Un objet est inutilisé si le programme ne contient plus de références à lui. Donc, dans votre test, je supprimerais explicitement la référence en définissant LotsOfBooleans sur null avant d'exécuter gc (); OU exécutez simplement main une fois avec booléen, une fois avec int puis comparez les nombres.
Randa Sbeity
2
@RandaSbeity Ou encore mieux: assurez-vous de conserver les deux références et de calculer la différence de mémoire. C'est exactement ce qui se passe ici.
biziclop
1
Y a-t-il une question à laquelle Jon Skeet ne peut pas répondre?
Andreas Hartmann
31

Les informations réelles représentées par une valeur booléenne en Java sont d'un bit: 1 pour vrai, 0 pour faux. Cependant, la taille réelle d'une variable booléenne en mémoire n'est pas définie avec précision par la spécification Java. Voir Types de données primitifs en Java .

Le type de données booléen n'a que deux valeurs possibles: true et false. Utilisez ce type de données pour les indicateurs simples qui suivent les conditions vrai / faux. Ce type de données représente un bit d'information, mais sa "taille" n'est pas définie avec précision.

William Brendel
la source
21

En passant ...

Si vous envisagez d'utiliser un tableau d'objets booléens, ne le faites pas. Utilisez plutôt un BitSet - il a quelques optimisations de performances (et quelques méthodes supplémentaires intéressantes, vous permettant d'obtenir le prochain bit set / unset).

Matthew Schinckel
la source
Ce n'est pas toujours vrai stackoverflow.com/questions/605226/…
Przemek
Cette réponse suggère qu'il y a des raisons significatives d'utiliser boolean [], mais comme l'indiquent les commentaires, il n'y a pas grand-chose à sauvegarder. Cela dit: je ne programme pas beaucoup en Java (et je n'ai fourni aucune preuve non plus;)
Matthew Schinckel
6

J'ai lu que Java réserve un octet pour un booleantype de données, mais il n'utilise qu'un seul bit. Cependant, la documentation dit que "sa" taille "n'est pas quelque chose qui est précisément défini" . Vois ici.

JavaNewbie_M107
la source
C'est un tutoriel, pas «la documentation». La documentation est le JLS, la spécification JVM et le Javadoc.
Marquis of Lorne
2

Les booleanvaleurs sont compilées en inttype de données dans JVM. Regardez ici .

rics
la source
2
Ce n'est pas nécessairement ainsi qu'ils sont stockés en mémoire, et je pense que c'est ce que la personne qui pose la question voulait savoir. Ce document décrit le format de fichier de classe (code d'octet compilé), pas la représentation d'une variable booléenne en mémoire, car cela dépend de l'implémentation.
William Brendel
2

La taille du booléen en java dépend de la machine virtuelle. mais tout objet Java est aligné sur une granularité de 8 octets. Un booléen a 8 octets d'en-tête, plus 1 octet de charge utile, pour un total de 9 octets d'informations. La JVM l'arrondit ensuite au multiple suivant de 8. Ainsi, la seule instance de java.lang.Boolean occupe 16 octets de mémoire.

Deepak Odedara
la source
J'aurai tendance à ne pas être d'accord, sur HotSpot JVM 1.7.0_51 l'en-tête a 12 octets + 1 pour le booléen + 3 pour la granularité.
Eugene
14
ne confondez pas booléen avec booléen.
andresp
1
Octets ou bits? 16 octets pour un monde Booleansoit un tel gaspillage ... c'est la taille d'un longqui peut transporter des milliards de fois plus d'informations qu'unBoolean
Dici
0

Ce n'est pas défini; faire des choses comme Jon Skeet l'a suggéré vous donnera une approximation sur une plate-forme donnée, mais le moyen de savoir précisément pour une plate-forme spécifique est d'utiliser un profileur.

Lawrence Dol
la source