Jaki jest rozmiar zmiennej boolowskiej w Javie?

89

Czy ktoś może określić wielkość bitową wartości logicznej w Javie?

DonX
źródło
1
To samo jest zadawane tutaj: stackoverflow.com/questions/1907318/ ...
dma_k

Odpowiedzi:

41

To zależy od maszyny wirtualnej.

Wojownik
źródło
9
Chcesz wskazać jakieś dokumenty? Trudno mi uwierzyć, że rozmiar wartości logicznej zależy od maszyny. Oznaczałoby to, że binarna reprezentacja klasy zawierającej wartość logiczną miałaby różne rozmiary (i układy pamięci) na różnych maszynach wirtualnych, co oznaczałoby, że maszyny wirtualne nie byłyby zgodne.
David Rodríguez - dribeas
14
Myślę, że zasugerowano, że pytanie dotyczy rozmiaru zmiennej boolowskiej w pamięci, a nie rozmiaru zmiennej boolowskiej zakodowanej w pliku klasy. Rozmiar pamięci zależy od maszyny wirtualnej zgodnie z dokumentacją firmy Sun. Rozmiar w pliku klasy jest stały.
William Brendel,
3
@ DavidRodríguez-dribeas - Sun JVM mniej więcej w czasach Java 1.1 wykorzystywał 4 bajty dla wartości logicznych, gdy był przechowywany jako instancja lub zmienna automatyczna. Uprościło to implementację interpretera kodu bajtowego (który uważa boole za zajmujące 4 bajty na stosie) i było ścieżką najmniejszego oporu. Kiedy wdrożyliśmy „klasyczną” maszynę JVM iSeries, znaleźliśmy sposoby na wykonanie zmiennej instancji o 1 bajcie, ponieważ znacznie poprawiło to zwartość niektórych obiektów (co ma niesamowity wpływ na wydajność). Najwyraźniej na podstawie poniższych postów programiści Sun / Oracle zorientowali się, jak zrobić to samo w późniejszych wersjach.
Hot Licks,
Ale to prawda, pod koniec 2017 roku JavaDocs mówi: boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined- ale twój punkt jest ważny,
przydałoby się
185

Zależy to od maszyny wirtualnej, ale łatwo jest dostosować kod z podobnego pytania z pytaniem o bajty w Javie :

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

Powtórzę, jest to zależne od maszyny wirtualnej, ale na moim laptopie z systemem Windows z JDK firmy Sun w wersji 1.6.0_11 otrzymałem następujące wyniki:

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

To sugeruje, że wartości logiczne mogą być w zasadzie pakowane w bajty przez JVM firmy Sun.

Jon Skeet
źródło
21
@skeet - Naprawdę cię pozdrawiam. Twoja odpowiedź jest niesamowita
Warrior
2
@warrior: Ponieważ dostałem już kod „bajtu”, zmiana go na „boolean” była całkiem prosta :)
Jon Skeet,
3
System.gc () nie gwarantuje czyszczenia pamięci. Po prostu wydaje JVM polecenie uruchomienia czyszczenia pamięci, ale nie oznacza to, że moduł zbierający faktycznie coś wyczyścił. Pamiętaj, że kolekcjoner czyści NIEUŻYWANE przedmioty. Obiekt jest nieużywany, jeśli program nie zawiera już odniesień do niego. Więc w twoim teście wyraźnie porzuciłbym odniesienie, ustawiając LotsOfBooleans na null przed uruchomieniem gc (); LUB po prostu uruchom main raz z wartością boolean, raz z int, a następnie porównaj liczby.
Randa Sbeity
2
@RandaSbeity Lub jeszcze lepiej: pamiętaj, aby zachować oba odniesienia i obliczyć różnicę pamięci. I właśnie tak się tutaj dzieje.
biziclop
1
Czy jest jakieś pytanie, na które Jon Skeet nie może odpowiedzieć?
Andreas Hartmann
31

Faktyczna informacja reprezentowana przez wartość logiczną w Javie to jeden bit: 1 dla prawdy, 0 dla fałszu. Jednak rzeczywisty rozmiar zmiennej boolowskiej w pamięci nie jest dokładnie zdefiniowany w specyfikacji Java. Zobacz prymitywne typy danych w Javie .

Logiczny typ danych ma tylko dwie możliwe wartości: prawda i fałsz. Użyj tego typu danych dla prostych flag, które śledzą warunki prawda / fałsz. Ten typ danych reprezentuje jeden bit informacji, ale jego „rozmiar” nie jest dokładnie zdefiniowany.

William Brendel
źródło
21

Na marginesie...

Jeśli myślisz o użyciu tablicy obiektów boolowskich, nie rób tego. Zamiast tego użyj BitSetu - ma pewne optymalizacje wydajności (i kilka fajnych dodatkowych metod, pozwalających na uzyskanie następnego ustawionego / nieustawionego bitu).

Matthew Schinckel
źródło
Nie zawsze to prawda. Stackoverflow.com/questions/605226/ ...
Przemek
Ta odpowiedź sugeruje, że istnieją ważne powody, aby używać wartości logicznych [], ale jak wskazują tam komentarze, nie ma zbyt wiele do poparcia. Powiedziawszy to: nie programuję zbyt wiele w Javie (i nie przedstawiłem też żadnych dowodów;)
Matthew Schinckel
6

Czytałem, że Java rezerwuje jeden bajt dla booleantypu danych, ale używa tylko jednego bitu. Jednak dokumentacja mówi, że „jego„ rozmiar ”nie jest dokładnie zdefiniowany” . Spójrz tutaj.

JavaNewbie_M107
źródło
To samouczek, a nie „dokumentacja”. Dokumentacja to JLS, JVM Spec. I Javadoc.
Markiz Lorne
2

Te booleanwartości są kompilowane do inttypu danych w JVM. Zobacz tutaj .

rics
źródło
2
Niekoniecznie tak są one przechowywane w pamięci i myślę, że właśnie to chciała wiedzieć osoba zadająca pytanie. Ten dokument opisuje format pliku klasy (skompilowany kod bajtowy), a nie reprezentację zmiennej boolowskiej w pamięci, ponieważ jest to zależne od implementacji.
William Brendel,
2

Rozmiar wartości logicznej w Javie zależy od maszyny wirtualnej. ale każdy obiekt Java jest wyrównany do 8-bajtowej szczegółowości. Boolean ma 8 bajtów nagłówka plus 1 bajt ładunku, co daje łącznie 9 bajtów informacji. Następnie maszyna JVM zaokrągla ją w górę do następnej wielokrotności liczby 8., więc jedna instancja java.lang.Boolean zajmuje 16 bajtów pamięci.

Deepak Odedara
źródło
Będę miał tendencję do nie zgadzania się, w HotSpot JVM 1.7.0_51 nagłówek ma 12 bajtów + 1 dla wartości logicznej + 3 dla szczegółowości.
Eugene
14
nie myl Boolean z boolean.
andresp
1
Bajty czy bity? 16 bajtów na zawsze Booleanbędzie marnotrawstwem ... to rozmiar a, longktóry może pomieścić bilion razy więcej informacji niż aBoolean
Dici,
0

To jest nieokreślone; robienie rzeczy, jak sugerował Jon Skeet, przyniesie przybliżenie na danej platformie, ale sposobem na dokładne poznanie konkretnej platformy jest użycie profilera.

Lawrence Dol
źródło