Когда выделяется память при создании экземпляра или при использовании нового ключевого слова для создания объекта?

1

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

  • 0
    Как вы писали дважды: память выделяется, когда создаются экземпляры. Точный размер обычно не имеет значения.
  • 0
    Выделенный объем памяти отличается от объекта к объекту
Показать ещё 1 комментарий
Теги:
memory-management

5 ответов

7

Переменные, объявленные в методе, хранятся в стеке, а фактические объекты хранятся в куче. Рассматривать

Integer a = new Integer(10);

В этом примере объект типа Integer создается в куче, и ссылка (32 или 64 бит) возвращается и сохраняется в стек меток как переменная 'a'. JVM может хранить такие переменные в пределах регистров процессора, если они предпочитают оптимизацию.

Память объекта выделяется при использовании нового ключевого слова. Обычно он назначается внутри TLAB (буфера локального распределения потоков), который является частью кучи eden, зарезервированной для текущего потока. Таким образом, сокращение накладных расходов на распределение объектов до простого "ударного указателя". Два раза, когда TLAB не используется, является 1) когда объект слишком велик для оставшегося пространства, в каком случае он будет продвигаться прямо к старым поколениям и 2) когда поддерживающая JVM решает посредством анализа эвакуации, что он может избежать объект полностью и выделяется непосредственно в стек (или даже разбивать объект отдельно и назначать только поля, необходимые для стека).

Объем зарезервированной памяти состоит из заголовка объекта, обычно 2 слова (3 для массива), а затем пробела для каждого из полей, объявленных в объекте и его родительских классах. Общий размер этих полей зависит от JVM и базовой платформы (например, 32 бит или 64 бит) и конфигурации JVM, таких как сжатые ссылки.

------------------+------------------+------------------ +--------------------------
|   mark word     |   klass pointer  |  array size (opt) |    padding and fields   |
------------------+------------------+-------------------+--------------------------

Просьба о JVM для размеров официально не поддерживается, но EHCache sizeOf - это очень хорошее "лучшее предположение", которое использует знания разных JVM и доступ к базовым указателям с использованием Java Unsafe.

Исходным местом для понимания размера каждого поля является размер примитивов, определенных языком Java, однако это только минимальные размеры, поскольку JVM предназначен для работы с 32 битами, и поэтому примитивы, меньшие, чем это, часто дополняются до 32 бит, Например, booleans.

Точная компоновка полей будет варьироваться в зависимости от JVM, но они будут сгруппированы по классу, который определяет их, начиная с корня дерева наследования. Например, рассмотрим

Изображение 174551

а также

Изображение 174551

Изображения, приведенные выше, были взяты из этого очень хорошего сообщения в блоге, которое очень хорошо описывает структуру памяти,

  • 0
    Что, если новое ключевое слово не используется?
  • 0
    @karmanaut В Java, если кто-то не использует ключевое слово new, он не создает объект. В каком случае, пожалуйста, уточните, какой случай вы рассматриваете.
2

"create instance" имеет то же значение, что "использовать new для создания нового объекта".

В нормальном случае память кучи будет выделена при запросе new объекта, но это не задано в камне: HotSpot также может определить, что безопасно выделять объект в стеке вызовов (в процессе Escape Анализ). Это более эффективно, так как не требуется сбор мусора.

Сколько выделено памяти имеет высокую специфичность для реализации, только Java-массивы гарантированно будут "упакованы" (по модулю фиксированные накладные расходы). Булевы массивы, однако, указаны как занимающие байты на элемент.

1

Я читаю ваш вопрос как: "Кто на самом деле выделяет память для объекта - new ключевое слово или конструктор?" Если это так, ответ будет ключевым словом new.

Конструкторы, как правило, цепочки, что означает, что по крайней мере два конструктора будут запускаться при создании экземпляра. С другой стороны, память для экземпляра выделяется только один раз.

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

Размер выделенной памяти таков, что он может содержать экземпляр типа, следующего за new ключевым словом. Последний размер (размер экземпляра типа)

  • совокупный размер примитивных типов (int, float, double и т.д.) состоит из,
  • плюс совокупный размер ссылок на ссылочные типы (экземпляры класса или интерфейса) состоит из,
  • плюс "секретный" материал, встроенный в экземпляры, чтобы функции Java могли работать (например, указатель виртуальной таблицы, чтобы обеспечить быстрое разрешение во время вызовов виртуальных методов)
  • плюс возможное дополнение между каждым из них (для согласования различных типов с их оптимальным количеством адресов в памяти).

В любом случае, когда вы делаете T obj1 = new T(), где T - это имя класса:

  1. Память выделяется где-то для размещения экземпляра T
  2. Экземпляр построен.
  3. Если экземпляр успешно создан, возвращается ссылка на экземпляр.
  4. Эта ссылка хранится в переменной obj1.

Когда вы выполняете R obj2 = new R(), аналогичная вещь происходит для типа R, а тип R может иметь разный размер, чем T

Но ни одна из этих локальных переменных не содержит экземпляр. Оба они содержат ссылку на назначенный объект. (Таким образом, сами переменные могут быть даже одного размера, если все, что им нужно сделать, это сохранить адрес памяти.)

  • 0
    да, правильно то, что вы говорите, но то, что я спрашиваю, заключается в следующей строке (forsomeclass fc; fc = new forsomeclass;) fc является ссылочной переменной и также является ли она экземпляром forsomeclass ??
  • 0
    @ Холмс я редактировал. Посмотрите, полностью ли он охватывает ваш вопрос сейчас.
Показать ещё 2 комментария
1

Поскольку я где-то читал, что память выделяется при создании экземпляров, а пространство выделяется из кучи.

да, вы правы, до тех пор, пока new будет называться просто null ссылкой, которая ничего не указывает.

Если это правильно, чем когда и насколько точно выделяется память при создании экземпляров и объектов?

Это зависит от размера объекта.

Взгляните на примитивные типы данных, чтобы узнать об их размере.

В Java, каков наилучший способ определить размер объекта?

Прочитайте больше...

  • 1
    сколько памяти выделено той ссылочной переменной, которая создается перед использованием нового ключевого слова?
  • 0
    ссылка не является объектом, и ссылка не находится в памяти кучи. Он держит в стеке.
Показать ещё 3 комментария
0

Переменные класса

Когда несколько объектов создаются из одного плана, каждый из них имеет свои собственные отдельные копии переменных экземпляра. В случае класса Bicycle переменными экземпляра являются каденция, передача и скорость. Каждый объект Bicycle имеет свои собственные значения для этих переменных, хранящихся в разных ячейках памяти.

Иногда вы хотите иметь переменные, общие для всех объектов. Это достигается с помощью статического модификатора. Поля, которые имеют статический модификатор в своем объявлении, называются статическими полями или переменными класса. Они связаны с классом, а не с каким-либо объектом. Каждый экземпляр класса использует переменную класса, которая находится в одном фиксированном месте в памяти. Любой объект может изменить значение переменной класса, но переменные класса также можно манипулировать, не создавая экземпляр класса.

https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

Ещё вопросы

Сообщество Overcoder
Наверх
Меню