Каков размер логической переменной в Java?

89

Может ли кто-нибудь сказать размер логического значения в Java?

DonX
источник
1
То же самое здесь: stackoverflow.com/questions/1907318/…
dma_k 08

Ответы:

41

Это зависит от виртуальной машины.

Воин
источник
9
Хотите указать на какие-то документы? Мне трудно поверить, что размер логического значения зависит от машины. Это означало бы, что двоичное представление класса, содержащего логическое значение, будет иметь разные размеры (и схемы памяти) в разных виртуальных машинах, и это будет означать, что виртуальные машины не будут совместимы.
Дэвид Родригес - дрибес
14
Я думаю, это подразумевалось, что вопрос относится к размеру логической переменной в памяти, а не к размеру логической переменной, закодированной в файле класса. Согласно документации Sun, размер памяти зависит от виртуальной машины. Размер в файле класса постоянный.
Уильям Брендель,
3
@ DavidRodríguez-dribeas - Sun JVM во времена Java 1.1 использовала 4 байта для логического значения при хранении в виде экземпляра или автоматической переменной. Это упростило реализацию интерпретатора байт-кода (который считает, что логические значения занимают 4 байта в стеке) и был путем наименьшего сопротивления. Когда мы реализовали "Classic" JVM iSeries, мы нашли способы сделать переменные экземпляра 1 байтовыми, так как это значительно улучшило компактность некоторых объектов (что очень сильно повлияло на производительность). Судя по сообщениям ниже, разработчики Sun / Oracle выяснили, как поступить аналогичным образом в более поздних версиях.
Hot Licks
Но это правильно, по состоянию на конец 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 под управлением Sun JDK build 1.6.0_11 я получил следующие результаты:

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

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

Джон Скит
источник
21
@skeet - я действительно приветствую вас. ваш ответ потрясающий
Warrior
2
@warrior: Поскольку у меня уже есть код для «байта», изменить его на «логическое» было довольно просто :)
Джон Скит
3
System.gc () не гарантирует очистки памяти. Он просто дает команду JVM запустить сборку мусора, но это не означает, что сборщик действительно что-то очистил. Помните, что сборщик убирает НЕИСПОЛЬЗУЕМЫЕ объекты. Объект не используется, если программа больше не содержит на него ссылок. Поэтому в вашем тесте я бы явно удалил ссылку, установив для LotsOfBooleans значение null перед запуском gc (); ИЛИ просто запустите main один раз с логическим значением, один раз с int, затем сравните числа.
Randa Sbeity
2
@RandaSbeity Или даже лучше: убедитесь, что вы сохранили обе ссылки и вычислите разницу в памяти. Именно это и происходит здесь.
biziclop
1
Есть ли вопрос, на который Джон Скит не может ответить?
Андреас Хартманн
31

Фактическая информация, представленная логическим значением в Java, составляет один бит: 1 - истина, 0 - ложь. Однако фактический размер логической переменной в памяти точно не определяется спецификацией Java. См. Примитивные типы данных в Java .

Тип данных boolean имеет только два возможных значения: true и false. Используйте этот тип данных для простых флагов, которые отслеживают истинные / ложные условия. Этот тип данных представляет один бит информации, но его «размер» не определен точно.

Уильям Брендель
источник
21

На стороне примечания ...

Если вы думаете об использовании массива логических объектов, не делайте этого. Вместо этого используйте BitSet - он имеет некоторую оптимизацию производительности (и несколько приятных дополнительных методов, позволяющих получить следующий бит установки / снятия).

Мэтью Шинкель
источник
Это не всегда так. Stackoverflow.com/questions/605226/…
Przemek
Этот ответ предполагает, что есть веские причины для использования boolean [], но, как показывают комментарии, его не так много. Сказав это: я мало программирую на Java (и не представил никаких доказательств;)
Мэтью Шинкель,
6

Я читал, что Java резервирует один байт для типа booleanданных, но использует только один бит. Однако в документации сказано, что «его« размер »не определен точно» . Глянь сюда.

JavaNewbie_M107
источник
Это учебник, а не «документация». Документация - это JLS, JVM Spec. И Javadoc.
Marquis of Lorne
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 для детализации.
Eugene
14
не путайте логическое значение с логическим.
andresp
1
Байты или биты? 16 байтов для мира Booleanбыть такой пустой тратой ... это размер a, longкоторый может нести в триллион раз больше информации, чем aBoolean
Дичи
0

Это не определено; выполнение таких вещей, как предложил Джон Скит, даст вам приблизительное представление о данной платформе, но способ узнать точно для конкретной платформы - использовать профилировщик.

Лоуренс Дол
источник