Чому boolean займає 1 байт

Чому boolean займає 1 байт



boolean та boolean[] Розмітка пам'яті в JVM

У цій швидкій статті ми побачимо, який вплив логічного значення в JVM за різних обставин.

Спочатку ми перевіримо JVM, щоб побачити розміри об'єктів. Тоді ми зрозуміємо обґрунтування цих розмірів.

2. Налаштування

Щоб перевірити розташування об'єктів у пам'яті в JVM, ми будемо широко використовувати Java Object Layout (JOL). Тому нам потрібно додати залежність jol-core: ``


dependency>


groupId>org.openjdk.jolgroupId>


artifactId>jol-coreartifactId>


version>0.10version>


dependency>

3. Розміри об'єктів

Якщо ми попросимо JOL роздрукувати інформацію про віртуальну машину з точки зору розмірів об'єктів:


System.out.println(VM.current().details());

Коли стислі посилання увімкнуті (за замовчуванням поведінка), ми побачимо висновок:


# Running 64-bit HotSpot VM.


# За допомогою compressed oop with 3-bit shift.


# За допомогою compressed klass with 3-bit shift.


# Objects are 8 bytes aligned.


# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]


# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

У перших кількох рядках ми можемо побачити деяку загальну інформацію про віртуальну машину. Після цього дізнаємося про розміри об'єктів:

  • Посилання Java займають 4 байти, boolean s / bytes - 1 байт, char s / short - 2 байти, int s / float - 4 байти і, нарешті, long s / double s - 8 байт. ``
  • Ці типи споживають однакову кількість пам'яті, навіть коли ми використовуємо їх як елементи масиву.

Отже, за наявності стиснених посилань кожне логічне значення займає 1 байт. Так само кожне логічне значення в boolean[] займає 1 байт. Однак відступи вирівнювання та заголовки об'єктів можуть збільшити простір, займаний логічними значеннями та логічними значеннями [], як ми побачимо пізніше.

3.1. Немає стислих посилань

Навіть якщо ми відключимо стислі посилання за допомогою -XX:-UseCompressedOops , логічний розмір взагалі не зміниться :


# Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]


# Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

З іншого боку, посилання Java займають удвічі більше, ніж пам'ять.

Таким чином, незважаючи на те, що ми могли б очікувати спочатку, логічні значення споживають 1 байт замість 1 біта.

3.2. Розрив слів

У більшості архітектур немає атомарного доступу до одного біта. Навіть якби ми захотіли це зробити, ми, мабуть, закінчили б запис у сусідні біти під час оновлення іншого.

Однією з цілей розробки JVM є запобігання цьому явищу, відомому як розрив слів . Тобто в JVM кожне поле та елемент масиву мають бути різними; оновлення одного поля або елемента не повинні взаємодіяти з читанням чи оновленням будь-якого іншого поля чи елемента.

Нагадаємо, що проблеми адресації та розриви слів є основними причинами, з яких логічні значення є чимось більшим, ніж один біт.

4. Звичайні покажчики об'єктів (ООП)

Тепер, коли ми знаємо, що логічні значення дорівнюють 1 байту, давайте розглянемо цей простий клас:


class
BooleanWrapper



private
boolean
value;


>

Якщо ми перевіримо розташування пам'яті цього класу за допомогою JOL:


System.out.println(ClassLayout.parseClass(BooleanWrapper.class).доPrintable());

Потім JOL надрукує макет пам'яті:


OFFSET SIZE TYPE DESCRIPTION VALUE

0
12
(object header)
N/A

12
1
boolean BooleanWrapper.value N/A

13
3
(loss due to the next object alignment)

Instance size:
16
bytes
Space losses:
0
bytes internal +
3
bytes external
=
3
bytes total

Макет BooleanWrapper складається з:

  • 12 байтів для заголовка, включаючи два слова мітки та одне слово класу . HotSpot JVM використовує слово мітки для зберігання метаданих збирача сміття, ідентифікаційного хеш-коду та інформації про блокування.Крім того, він використовує слово klass для зберігання метаданих класу, таких як тип перевірки типу під час виконання.
  • 1 байт для фактичного логічного значення
  • 3 байти заповнення для цілей вирівнювання

За замовчуванням посилання на об'єкти мають бути вирівняні по 8 байт. Тому JVM додає 3 байти до 13 байтів заголовка та логічного значення, щоб отримати 16 байтів.

Отже, логічні поля можуть споживати більше пам'яті через їхнє вирівнювання полів.

4.1. Вирівнювання користувача

Якщо змінимо значення вирівнювання на 32 за допомогою -XX:ObjectAlignmentInBytes=32, той самий макет класу зміниться на:


OFFSET SIZE TYPE DESCRIPTION VALUE

0
12
(object header)
N/A

12
1
boolean BooleanWrapper.value N/A

13
19
(loss due to the next object alignment)

Instance size:
32
bytes
Space losses:
0
bytes internal +
19
bytes external
=
19
bytes total

Як показано вище, JVM додає 19 байтів заповнення, щоб зробити розмір об'єкта кратним 32.

5. Масив ООП

Давайте подивимося, як JVM розміщує логічний масив у пам'яті:


boolean[]
value
=
new
boolean[3];


System.out.println(ClassLayout.parseInstance(value).доPrintable());

Це надрукує макет екземпляра так:


OFFSET SIZE TYPE DESCRIPTION


0
4
(object header)
# mark word


4
4
(object header)
# mark word


8
4
(object header)
# klass word


12
4
(object header)
# array length


16
3
boolean
[Z.elements>
# [Z means boolean array


19
5
(loss due to the next object alignment)

Крім двох слів-міток і одного слова-класу, покажчики масиву містять додаткові 4 байти для зберігання їх довжини.

Оскільки наш масив складається із трьох елементів, розмір елементів масиву дорівнює 3 байтам. Однак ці 3 байти будуть доповнені 5 байтами вирівнювання полів для забезпечення правильного вирівнювання.

Хоча розмір кожного логічного елемента в масиві становить лише 1 байт, весь масив займає набагато більше пам'яті. Іншими словами, ми повинні враховувати накладні витрати на заголовок та заповнення при обчисленні розміру масиву.

6. Висновок

У цьому короткому посібнику ми побачили, що логічні поля займають 1 байт. Крім того, ми дізналися, що слід враховувати накладні витрати на заголовок та заповнення у розмірах об'єкта.

Для більш детального обговорення рекомендується ознайомитися з розділом oops вихідного коду JVM. Також Олексій Шипільов має набагато глибшу статтю на цю тему.

Як завжди, всі приклади доступні на GitHub.

Boolean (Булев, Логічний тип даних)

Boolean (Булев, Логічний тип даних) - Примітивний тип даних в інформатиці, які можуть набувати два можливих значення, іноді званих істиною (true) і брехнею (false). Наприклад, у JavaScript Булеві стани часто використовуються для того, щоб визначити, які частини коду виконувати (наприклад, в операторах if) або повторювати (наприклад, цикли for).

Нижче наведений певний псевдокод JavaScript (це не справді виконуваний код), що демонструє цю концепцію.

Приклад використання оператора if:

Приклад використання логічної умови в циклі for:

for (початок; умова; крок) < // . тіло циклу. >

Булеви значення названо на честь англійського математика Джорджа Буля, який був першопрохідником у галузі математичної логіки.

Дивіться також

Технічна довідка

Розмір змінних типу boolean та byte

також повертає 1, хоча, теоретично, boolean зберігає один біт інформації. На змінну не можна виділити дрібне число байт, чи що?

2 відповіді 2

Так само, як char або byte, boolean займає 1 байт (8 біт), щоб зберігати значення 1 або 0, true / false .

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

P.S. у деяких мовах резервується 2 байти.

Не зовсім коректна фраза про значення 0 та 1, якщо беремо загальне визначення, а не лише для FreePascal. Різні мови зберігають True по-різному. Сходяться тільки в одному: False - це 0. А ось True в Delphi = -1($FF), FreePascal і в C(емніп) = 1($1). Але це встановлення значення. А ось перевірка (порівняння) ведеться саме за єдиною умовою (її бере на себе компілятор): 0 = False, не 0 = True, інакше була б неможлива стикування з іншими мовами.

Подібні статті

Останні статті

Категорії