Який розмір булевої змінної в Java?


89

Чи може хтось сказати бітовий розмір логічного значення в Java?


1
Запитав тут Про те ж: stackoverflow.com/questions/1907318 / ...
dma_k

Відповіді:


41

Це залежить від віртуальної машини.


9
Хочете вказати на деякі документи? Мені важко повірити, що розмір логічного значення залежить від машини. Це означало б, що двійкове представлення класу, що містить логічне значення, мало б різний розмір (і макети пам’яті) в різних ВМ, і це означало б, що ВМ не будуть сумісними.
Девід Родрігес - dribeas

14
Я думаю, малося на увазі, що питання стосується розміру логічної змінної в пам'яті, а не розміру логічної змінної, закодованої у файлі класу. Обсяг пам'яті залежить від віртуальної машини відповідно до документації Sun. Розмір у файлі класу постійний.
Вільям Брендель

3
@ DavidRodríguez-dribeas - Sun JVM за часів Java 1.1 використовував 4 байти для логічного значення, коли зберігався як екземпляр або автоматична змінна. Це спростило реалізацію інтерпретатора байт-коду (який розглядає були як такі, що займають 4 байти в стеку) і стало шляхом найменшого опору. Коли ми впровадили iSeries "Classic" JVM, ми знайшли способи зробити екземпляр змінним 1 байт, оскільки це значно покращило компактність деяких об'єктів (що надзвичайно впливає на продуктивність). Очевидно, на основі публікацій нижче, розробники Sun / Oracle придумали, як це зробити в пізніших версіях.
Hot Licks 02

Але це правильно, станом на кінець 2017 року JavaDocs кажуть: boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined- але ваша думка дійсна, вона може використовувати деякі посилання та кращу інформацію :)
JimLohse

185

Це залежить від віртуальної машини, але легко адаптувати код із подібного запитання про байти в 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();
    }
}

Знову ж таки, це залежить від віртуальної машини, але на своєму ноутбуці з ОС Windows, що працює під управлінням JDK build 1.6.0_11 від Sun, я отримав такі результати:

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

Це свідчить про те, що логічні значення в основному можуть бути упаковані в байт кожен JVM Sun.


21
@skeet - Я справді вітаю тебе. твоя відповідь чудова
Воїн

2
@warrior: Оскільки я вже отримав код для "байт", змінити його на "логічний" було досить просто :)
Джон Скіт,

3
System.gc () не гарантує очищення пам'яті. Це просто дає наказ JVM запустити збір сміття, але це не означає, що колектор насправді щось очистив. Пам’ятайте, що колектор очищає НЕВИКОРИСТАНІ об’єкти. Об'єкт не використовується, якщо програма більше не містить посилань на нього. Отже, у вашому тесті я б явно скинув посилання, встановивши LotsOfBooleans на null перед запуском gc (); АБО просто запустіть main один раз за допомогою логічного значення, один раз за допомогою int, тоді порівняйте числа.
Randa Sbeity

2
@RandaSbeity Або навіть краще: обов’язково збережіть обидва посилання та обчисліть різницю пам’яті. Що саме тут і відбувається.
biziclop

1
Чи є якесь запитання, на яке Джон Скіт не може відповісти?
Andreas Hartmann,

31

Фактична інформація, представлена ​​булевим значенням у Java, становить один біт: 1 для true, 0 для false. Однак фактичний розмір булевої змінної в пам'яті не точно визначений специфікацією Java. Див. Примітивні типи даних у Java .

Логічний тип даних має лише два можливих значення: true і false. Використовуйте цей тип даних для простих прапорів, які відстежують істинні / хибні умови. Цей тип даних представляє один біт інформації, але його "розмір" не є точно визначеним.


21

На замітці ...

Якщо ви думаєте про використання масиву булевих об'єктів, ні. Замість цього використовуйте BitSet - він має деякі оптимізації продуктивності (і кілька приємних додаткових методів, що дозволяють отримати наступний біт / встановлений біт).


Це не завжди правда stackoverflow.com/questions/605226/…
Przemek

Ця відповідь свідчить про те, що є серйозні причини використовувати логічну форму [], але, як вказують там коментарі, не так багато для її резервного копіювання. Сказавши це: Я не дуже багато програмую на Java (і також не надав жодних доказів;)
Метью Шинкель,

6

Я читав, що Java резервує один байт для booleanтипу даних, але він використовує лише один біт. Однак у документації сказано, що "його" розмір "не є точно визначеним" . Дивіться тут.


Це підручник, а не "документація". Документацією є JLS, JVM Spec. Та Javadoc.
Маркіз Лорнський

2

Ці booleanзначення зведені до intтипу даних в JVM. Дивіться тут .


2
Це не обов'язково те, як вони зберігаються в пам'яті, і я думаю, що саме це хотів би знати той, хто задає питання. Цей документ описує формат файлу класу (скомпільований байт-код), а не подання булевої змінної в пам’яті, оскільки це залежить від реалізації.
Вільям Брендель

2

Розмір логічного значення в Java залежить від віртуальної машини. але будь-який об'єкт Java вирівнюється до 8 байт деталізації. Логічне значення має 8 байт заголовка, плюс 1 байт корисного навантаження, загалом 9 байт інформації. Потім JVM округлює його до наступного кратного 8. Таким чином, один екземпляр java.lang.Boolean займає 16 байт пам'яті.


Я, як правило, не погоджуюся, на HotSpot JVM 1.7.0_51 заголовок має 12 байт + 1 для логічного значення + 3 для деталізації.
Євген

14
не плутайте булеве з булевим.
andresp

1
Байти або біти? 16 байтів для Booleanпростору - це таке марнотратство ... це розмір, longякий може нести в трильйони разів більше інформації, ніж aBoolean
Дічі

0

Це невизначено; виконуючи такі дії, як запропонував Джон Скіт, ви отримаєте наближення на певній платформі, але спосіб точно знати для певної платформи - це використання профілі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.