Wie groß ist eine boolesche Variable in Java?

89

Kann jemand die Bitgröße von Boolean in Java sagen ?

DonX
quelle
1
Das gleiche wird hier gefragt: stackoverflow.com/questions/1907318/…
dma_k

Antworten:

41

Es ist abhängig von der virtuellen Maschine.

Krieger
quelle
9
Möchten Sie auf einige Dokumente verweisen? Es fällt mir schwer zu glauben, dass die Größe eines Booleschen Wertes maschinenabhängig ist. Das würde bedeuten, dass die binäre Darstellung einer Klasse, die einen Booleschen Wert enthält, unterschiedliche Größen (und Speicherlayouts) in unterschiedlichen VMs haben würde, und dies würde bedeuten, dass VMs nicht kompatibel wären.
David Rodríguez - Dribeas
14
Ich denke, es wurde impliziert, dass sich die Frage auf die Größe einer booleschen Variablen im Speicher bezieht, nicht auf die Größe einer booleschen Variablen, die in einer Klassendatei codiert ist. Die Größe des Speichers variiert je nach VM gemäß der Dokumentation von Sun. Die Größe in der Klassendatei ist konstant.
William Brendel
3
@ DavidRodríguez-dribeas - Die Sun JVM zur Zeit von Java 1.1 verwendete 4 Bytes für Boolesche Werte, wenn sie als Instanz oder Auto-Var gespeichert wurde. Dies vereinfachte die Implementierung des Bytecode-Interpreters (der Bools als 4 Byte auf dem Stapel belegend ansieht) und war der Weg des geringsten Widerstands. Bei der Implementierung der iSeries "Classic" -JVM haben wir Möglichkeiten gefunden, Instanzvariablen auf 1 Byte zu setzen, da dies die Kompaktheit einiger Objekte erheblich verbessert (was sich erstaunlich auf die Leistung auswirkt). Anscheinend haben die Sun / Oracle-Entwickler anhand der folgenden Beiträge herausgefunden, wie dies auch in späteren Versionen zu tun ist.
Hot Licks
Aber es ist richtig, ab Ende 2017 sagen JavaDocs : boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined- aber Ihr Punkt ist gültig, es könnte einige Links und bessere Informationen verwenden :)
JimLohse
185

Dies hängt von der virtuellen Maschine ab, aber es ist einfach, den Code anhand einer ähnlichen Frage zu Bytes in Java anzupassen :

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();
    }
}

Um es noch einmal zu wiederholen: Dies ist VM-abhängig, aber auf meinem Windows-Laptop mit Suns JDK Build 1.6.0_11 habe ich die folgenden Ergebnisse erhalten:

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

Dies deutet darauf hin, dass Boolesche Werte von Suns JVM grundsätzlich jeweils in ein Byte gepackt werden können.

Jon Skeet
quelle
21
@skeet - Ich grüße Sie wirklich. Ihre Antwort ist fantastisch
Warrior
2
@warrior: Da ich den Code für "Byte" bereits erhalten hatte, war es ziemlich einfach, ihn in "Boolean" zu ändern :)
Jon Skeet
3
System.gc () garantiert keine Reinigung des Speichers. Es gibt der JVM lediglich den Befehl, die Garbage Collection auszuführen, aber dies bedeutet nicht, dass der Collector tatsächlich etwas bereinigt hat. Denken Sie daran, dass der Sammler nicht verwendete Objekte bereinigt. Ein Objekt wird nicht verwendet, wenn das Programm keine Verweise mehr darauf enthält. In Ihrem Test würde ich die Referenz explizit löschen, indem ich LotsOfBooleans auf null setze, bevor gc () ausgeführt wird. ODER führen Sie main einmal mit boolean aus, einmal mit int und vergleichen Sie dann die Zahlen.
Randa Sbeity
2
@RandaSbeity Oder noch besser: Stellen Sie sicher, dass Sie beide Referenzen beibehalten und die Speicherdifferenz berechnen. Welches ist genau das, was hier passiert.
Biziclop
1
Gibt es eine Frage, die Jon Skeet nicht beantworten kann?
Andreas Hartmann
31

Die tatsächliche Information, die in Java durch einen booleschen Wert dargestellt wird, ist ein Bit: 1 für wahr, 0 für falsch. Die tatsächliche Größe einer booleschen Variablen im Speicher wird jedoch durch die Java-Spezifikation nicht genau definiert. Siehe Primitive Datentypen in Java .

Der boolesche Datentyp hat nur zwei mögliche Werte: true und false. Verwenden Sie diesen Datentyp für einfache Flags, die True / False-Bedingungen verfolgen. Dieser Datentyp stellt ein Informationsbit dar, aber seine "Größe" ist nicht genau definiert.

William Brendel
quelle
21

Als Randnotiz...

Wenn Sie über die Verwendung eines Arrays von Booleschen Objekten nachdenken, tun Sie dies nicht. Verwenden Sie stattdessen ein BitSet - es enthält einige Leistungsoptimierungen (und einige nette zusätzliche Methoden, mit denen Sie das nächste gesetzte / nicht gesetzte Bit erhalten können).

Matthew Schinckel
quelle
Dies ist nicht immer wahr stackoverflow.com/questions/605226/…
Przemek
Diese Antwort deutet darauf hin, dass es wichtige Gründe für die Verwendung von boolean [] gibt, aber wie die Kommentare dort zeigen, gibt es nicht viel, um dies zu sichern. Trotzdem: Ich programmiere nicht viel in Java (und habe auch keine Beweise geliefert;)
Matthew Schinckel
6

Ich habe gelesen, dass Java ein Byte für einen booleanDatentyp reserviert , aber nur ein Bit verwendet. Die Dokumentation besagt jedoch, dass "seine" Größe "nicht genau definiert ist" . Siehe hier.

JavaNewbie_M107
quelle
Das ist ein Tutorial, nicht 'die Dokumentation'. Die Dokumentation ist JLS, JVM Spec. Und Javadoc.
Marquis von Lorne
2

Die booleanWerte werden intin JVM zum Datentyp kompiliert . Siehe hier .

rics
quelle
2
Auf diese Weise werden sie nicht unbedingt gespeichert, und ich denke, das wollte die Person, die die Frage gestellt hat, wissen. Dieses Dokument beschreibt das Klassendateiformat (kompilierter Bytecode) und nicht die Darstellung einer booleschen Variablen im Speicher, da dies implementierungsabhängig ist.
William Brendel
2

Die Größe des Booleschen Werts in Java hängt von der virtuellen Maschine ab. Jedes Java-Objekt ist jedoch auf eine 8-Byte-Granularität ausgerichtet. Ein Boolescher Wert enthält 8 Byte Header plus 1 Byte Nutzlast für insgesamt 9 Byte Information. Die JVM rundet es dann auf das nächste Vielfache von 8 auf, sodass die eine Instanz von java.lang.Boolean 16 Byte Speicher belegt.

Deepak Odedara
quelle
Ich werde eher anderer Meinung sein, auf HotSpot JVM 1.7.0_51 hat der Header 12 Bytes + 1 für den Booleschen Wert + 3 für die Granularität.
Eugene
14
Verwechseln Sie Boolean nicht mit Boolean.
andresp
1
Bytes oder Bits? 16 Bytes für eine Welt Booleansind so eine Verschwendung ... das ist die Größe einer, longdie Billionen Mal mehr Informationen enthalten kann als eineBoolean
Dici
0

Es ist undefiniert; Wenn Sie Dinge tun, wie sie von Jon Skeet vorgeschlagen wurden, erhalten Sie eine Annäherung an eine bestimmte Plattform. Um jedoch genau über eine bestimmte Plattform Bescheid zu wissen, müssen Sie einen Profiler verwenden.

Lawrence Dol
quelle