Статическое распределение в java - куча, стек и постоянное поколение

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

  • Классы (загружаемые загрузчиками классов) входят в специальную область в кучу: Постоянное поколение
  • Вся информация, относящаяся к классу, как имя класса, массивы объектов, ассоциированные с классом, внутренние объекты, используемые JVM (например, java/lang/Object), и информация о оптимизации поступают в область постоянного поколения.
  • Все статические переменные-члены снова сохраняются в области Постоянный уровень.
  • Объекты идут в другую кучу: молодое поколение
  • Существует только одна копия каждого метода для каждого класса, будь то статический или нестатический метод. Эта копия помещается в область постоянного поколения. Для нестатических методов все параметры и локальные переменные попадают в стек - и всякий раз, когда есть конкретный вызов этого метода, мы получаем новый связанный с ним стек-фрейм. Я не уверен, где хранятся локальные переменные статического метода. Они находятся в куче постоянного поколения? Или просто их ссылка хранится в области постоянного поколения, а фактическая копия находится где-то в другом месте (где?).
  • Я также не знаю, где будет сохраняться возвращаемый тип метода.
  • Если объекты (в молодом поколении) должны использовать статический член (в постоянном поколении), им предоставляется ссылка на статический член && & им предоставляется достаточное пространство памяти для хранения возвращаемого типа метода и т.д.

Благодарим вас за это!

Ответы

Ответ 1

Во-первых, как вам должно быть ясно, что очень мало людей, которые могут подтвердить эти ответы из первых рук. Очень немногие люди работали над недавними JVM HotSpot или изучали их на глубину, необходимую для того, чтобы действительно знать. Большинство людей здесь (включая меня) отвечают на основании того, что они видели, написанного в другом месте, или того, что они вывели. Обычно то, что написано здесь, или в различных статьях и веб-страницах, основано на других источниках, которые могут быть или не быть окончательными. Часто это упрощается, неточно или просто неправильно.

Если вы хотите окончательное подтверждение своих ответов, вам действительно нужно загрузить исходный код OpenJDK... и провести собственное исследование, прочитав и поняв исходный код. Задавать вопросы по SO или тралить через случайные веб-статьи не является хорошей научной методикой исследования.

Сказав, что...

1) Классы (загруженные загрузчиками классов) идут в специальную область в куче: Постоянное поколение.

AFAIK, да. ( Обновить: см. ниже.)

2) Вся информация, относящаяся к классу, как имя класса, массивы объектов, ассоциированные с классом, внутренние объекты, используемые JVM (например, java/lang/Object), и информация о оптимизации поступают в область постоянного поколения.

Более или менее, да. Я не уверен, что вы подразумеваете под некоторыми из этих вещей. Я предполагаю, что "внутренние объекты, используемые JVM (например, java/lang/Object)", означают дескрипторы внутреннего класса JVM.

3) Все статические переменные-члены снова сохраняются в области постоянного поколения.

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

4) Объекты идут в другую кучу: молодое поколение

Не обязательно. Большие объекты могут быть выделены непосредственно в поколение.

5) Существует только одна копия каждого метода для каждого класса, будь то статический или нестатический метод. Эта копия помещается в область постоянного поколения.

Предполагая, что вы имеете в виду код метода, тогда AFAIK да. Однако может быть немного сложнее. Например, этот код может существовать в байт-кодах и/или в собственных кодовых формах в разное время жизни JVM.

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

Да.

... Я не уверен, где хранятся локальные переменные статического метода. Являются ли они на куче постоянного гения? Или просто их ссылка хранится в области постоянного поколения, а фактическая копия находится где-то в другом месте (где?)

Нет. Они хранятся в стеке, как и локальные переменные в нестатических методах.

6) Я также не знаю, где будет сохраняться возвращаемый тип метода.

Если вы имеете в виду значение, возвращаемое вызовом метода (не-void), то оно возвращается либо в стек, либо в машинный регистр. Если он возвращается в стек, это занимает 1 или два слова, в зависимости от типа возврата.

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

Это неточно (или, по крайней мере, вы явно не выражаете себя).

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

  • Ни в коем случае новое хранилище не должно выделяться для хранения ссылочного или примитивного значения.

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

  • Ни в коем случае не нужно выделять пространство вызывающим абонентом для хранения некоторого объекта/массива, возвращаемого методом. В Java объекты и массивы всегда возвращаются с использованием семантики pass-by-value... но это возвращаемое значение является ссылкой на объект или массив.

UPDATE

С Java 8 пространство PermGen заменено на Metaspace. Для получения дополнительной информации см. Эти ресурсы: