Класс минимизирует использование памяти: если переменная экземпляра объекта (non-primitive) равна нулю, она все еще использует необходимые опорные байты?

В настоящее время я разрабатываю структуру данных, в которой я пытаюсь свести потребление памяти к минимуму. У меня есть несколько переменных экземпляра, которые могут быть нулевыми в зависимости от размещения Node в Trie. Я начал спускаться по пути создания отдельных классов (тот, у которого есть переменная экземпляра, а другая - нет), так что я не буду тратить массу пространства с нулевыми ссылками... но потом я начал задаваться вопросом, как работает jvm, Остается ли до сих пор до 8 байтов (при условии, что x64-арка), если ссылка на объект равна нулю или у нее есть более оптимальный способ хранения нулевой ссылки?

4 ответа

Я почти уверен, что JVM будут использовать столько места для ссылки null, как для любой другой. Если у вас есть объект с тремя ссылочными полями, и вы исключаете его из середины, я не думаю, что какая-либо виртуальная машина сможет переместить 3-ей и сохранить 4 или 8 байтов (а затем, когда вы измените null к чему-то еще, ему придется снова перемещать вещи). Если бы это было технически осуществимо, это не стоило бы - дополнительные вычислительные затраты и сложность кода убьют любые потенциальные выгоды. Кроме того, частично из-за наследия C, на большинстве машин указатель, равный по битту 0, работает как NULL на очень низком уровне, поэтому ссылка null имеет довольно очевидное представление.

В Oracle/Sun JDK вы можете использовать - XX: + UseCompressedOops аргумент командной строки, чтобы сделать ссылки на 4 байта вместо 8 на 64-битных если ваша куча меньше 16 ГБ (независимо от того, является ли эта ссылка null или нет).


Ответ: yes Он по-прежнему использует необходимые байты. В Java значение null - это просто значение, которое может иметь ссылка. Это означает, что ссылка ссылается на ничего. В этом случае вы все еще занимаете пространство для ссылки. Это 4 байта в 32-битных системах или 8 байтах в 64-битных системах.

См. Нулевая переменная требует пространства в памяти


Мы можем добавить простой математический пример: предположим, что у вас есть объект с полем типа int, что 4 байта для любой архитектуры, которая может быть undefined (это зависит от варианта использования, какое значение должно принимать поле вы могли бы понять, что это undefined). Теперь, если он определен, вы используете 4 байта. Если он не определен, вы теряете 4 байта.

Предположим, вы завернули его в объект. Теперь, если поле определено, оно использует 4 или 8 байтов (в зависимости от бит JVM и сжатия указателя, включенного или выключенного с помощью -XX:+UseCompressedOops) для указателя. Объект с одиночным 4-байтовым полем будет потреблять 16 байтов независимо от битности (объект будет занимать 16 байтов как в 32-битной, так и в 64-битной Java-среде исполнения, так как он содержит 8 или 12 байтов заголовка объекта и 4 байта значения, а используемая память выравнивается ближайших 8 байтов).

Подводя итог, если вы придерживаетесь примитива, вы будете использовать 4 байта. Если вы поместите один int в объект, вы будете использовать 20 или 24 байта, если поле имеет значение; и 4 или 8 байтов, если значение равно null.


Классы и суперклассы также используют некоторые байты.

Если вы действительно хотите избежать использования большей части памяти, я предлагаю использовать шаблон FlyWeight

(Идеи: повторно использовать одни и те же неизменяемые объекты, создавать factory и кэшировать их).

Ваш код становится немного сложнее, что плохо. Но вы можете много экономить на памяти.

Другой выбор - работать с более простыми типами (а не с объектами). Это менее практично, но вы должны делать все извне на своих данных... Поэтому я предпочитаю FlyWeight.

licensed under cc by-sa 3.0 with attribution.