Почему не определен логический примитив Java? - PullRequest
106 голосов
/ 15 декабря 2009

В спецификации виртуальной машины Java говорится, что ограниченная поддержка логических примитивных типов.

Нет никаких инструкций виртуальной машины Java, предназначенных исключительно для операций с булевыми значениями. Вместо этого выражения на языке программирования Java, которые работают с логическими значениями, компилируются для использования значений типа данных виртуальной машины Java int.

Вышесказанное подразумевает (хотя я, возможно, неверно истолковал его), что тип данных int используется при работе с логическими значениями, но это 32-разрядная конструкция памяти. Учитывая, что логическое значение представляет только 1 бит информации:

  • Почему байтный или короткий тип не используется в качестве прокси для логического значения вместо int?
  • Для какой-либо конкретной JVM, какой самый надежный способ точно определить, сколько памяти используется для хранения логического типа?

Ответы [ 7 ]

111 голосов
/ 15 декабря 2009

Краткий ответ: да, логические значения обрабатываются как 32-битные объекты, но массивы логических значений используют 1 байт на элемент.

Более длинный ответ: JVM использует 32-битную ячейку стека, используемую для хранения локальных переменных, аргументов метода и значений выражений. Примитивы, размер которых меньше 1 ячейки, дополняются, примитивы размером более 32 бит (длинные и двойные) занимают 2 ячейки. Этот метод минимизирует количество кодов операций, но имеет некоторые специфические побочные эффекты (например, необходимость маскировать байты).

Примитивы, хранящиеся в массивах, могут использовать менее 32 бит, и существуют разные коды операций для загрузки и хранения значений примитивов из массива. И логические, и байтовые значения используют коды операций baload и bastore, что означает, что логические массивы занимают 1 байт на элемент.

Что касается компоновки объекта в памяти, то это рассматривается в «частной реализации» правилах , оно может быть 1 битом, 1 байтом или, как заметил другой участник, выровнено по бит двойная граница слова. Скорее всего, он принимает базовый размер слова базового оборудования (32 или 64 бита).


Что касается сведения к минимуму объема пространства, используемого булевыми значениями: это действительно не проблема для большинства приложений. Кадры стека (содержащие локальные переменные и аргументы метода) не очень велики, и в большой схеме дискретный логический объект в объекте также не так велик. Если у вас много объектов с большим количеством логических значений, вы можете использовать битовые поля, которые управляются через ваши методы получения и установки. Тем не менее, вы будете платить штраф в процессорном времени, который, вероятно, больше, чем штраф в памяти.

7 голосов
/ 15 декабря 2009

Один логический объект где-то в иерархии наследования может использовать до 8 байт! Это из-за заполнения. Более подробную информацию можно найти в Сколько памяти используется моим Java-объектом? :

Возвращаясь к вопросу о том, как много логическое потребляет, да, это делает потреблять хотя бы один байт, но из-за правила выравнивания это может потреблять много Больше. ИМХО это интереснее знать, что логическое значение [] будет потреблять один байт на запись, а не один бит, плюс некоторые накладные расходы из-за выравнивания и для поле размера массива. Есть графовые алгоритмы, где большие поля биты полезны, и вы должны быть Помните, что если вы используете логическое значение [], вы нужно почти ровно в 8 раз больше памяти, чем действительно нужно (1 байт против 1 бита).

5 голосов
/ 07 января 2010

Пятое издание Java в двух словах (О'Рейли) говорит, что тип логического примитива составляет 1 байт. Это может быть неправильно, основываясь на том, что показывает проверка кучи. Интересно, есть ли у большинства JVM проблемы с выделением переменных для байта меньше байта.

3 голосов
/ 15 декабря 2009

Логическое отображение было выполнено с учетом 32-битного процессора. Значение int имеет 32 бита, поэтому оно может быть обработано за одну операцию.

Вот решение от Java IAQ Питера Норвига: Нечасто отвеченные вопросы для измерения размера (с некоторой неточностью):

static Runtime runtime = Runtime.getRuntime();
...
long start, end;
Object obj;
runtime.gc();
start = runtime.freememory();
obj = new Object(); // Or whatever you want to look at
end =  runtime.freememory();
System.out.println("That took " + (start-end) + " bytes.");
1 голос
/ 19 января 2013

Boolean представляет один бит информации, но его «размер» не является чем-то точно определенным, говорят учебники по Sun Java. Булевы литералы имеют только два возможных значения: true и false. Подробнее см. Типы данных Java .

1 голос
/ 15 декабря 2009

ЦП работают с определенной длиной типа данных. В случае 32-битных процессоров они имеют длину 32 бита и, следовательно, то, что вы называете «int» в Java. Все, что ниже или выше, должно быть заполнено или разделено на эту длину, прежде чем ЦП сможет его обработать. Это не займет много времени, но если вам требуется 2 такта процессора вместо 1 для основных операций, это означает удвоение затрат / времени.

Эта спецификация предназначена для 32-битных процессоров, чтобы они могли обрабатывать логические значения со своим собственным типом данных.

У вас может быть только одно: скорость или память - SUN выбрал скорость.

0 голосов
/ 15 декабря 2009

Почему бы не сделать один файл .java следующим образом:

Empty.java

class Empty{
}

и один класс вроде этого:

NotEmpty.java

class NotEmpty{
   boolean b;
}

Скомпилируйте их оба и сравните файлы .class с помощью шестнадцатеричного редактора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...