Статическое распределение в java - куча, стек и постоянная генерация
В последнее время я много читал о схемах выделения памяти в Java, и было много сомнений, поскольку я читал из разных источников. Я собрал свои концепции, и я бы попросил пройтись по всем пунктам и прокомментировать их. Я узнал, что распределение памяти зависит от JVM, поэтому я должен сказать заранее, что мой вопрос касается Sun.
- Классы (загружаемые загрузчиками классов) помещаются в специальную область в куче: Permanent Generation
- Вся информация, относящаяся к классу, такая как имя класса, массивы объектов, связанные с классом, внутренние объекты, используемые JVM (например, java/lang/Object) и информация об оптимизации, попадает в область постоянного создания.
- Все статические переменные-члены снова сохраняются в области постоянной генерации.
- Объекты уходят в другую кучу: молодое поколение
- В каждом классе есть только одна копия каждого метода, будь то метод статический или нестатический. Эта копия помещается в область постоянного поколения. Для нестатических методов все параметры и локальные переменные отправляются в стек - и всякий раз, когда происходит конкретный вызов этого метода, мы получаем новый кадр стека, связанный с ним. Я не уверен, где хранятся локальные переменные статического метода. Они в куче постоянного поколения? Или просто их ссылка хранится в области постоянного поколения, а фактическая копия находится где-то еще (где?)
- Я также не уверен, где хранится возвращаемый тип метода.
- Если объектам (в молодом поколении) необходимо использовать статический член (в постоянном поколении), им дают ссылку на статический член &&, им достаточно места в памяти для хранения возвращаемого типа метода и т. Д.
Спасибо, что прошли через это!
1 ответ
Во-первых, как вам должно быть ясно сейчас, очень мало людей могут подтвердить эти ответы из первых рук. Очень немногие люди работали над недавними JVM HotSpot или изучали их до глубины, необходимой, чтобы действительно знать. Большинство людей здесь (включая меня) отвечают на основании того, что они видели написанным в другом месте, или того, что они сделали вывод. Обычно то, что написано здесь или в различных статьях и на веб-страницах, основано на других источниках, которые могут быть или не быть окончательными. Часто это упрощенно, неточно или просто неправильно.
Если вы хотите получить окончательное подтверждение своих ответов, вам действительно нужно скачать исходный код OpenJDK... и провести собственное исследование, прочитав и поняв исходный код. Задавать вопросы о SO или обходить случайные веб-статьи не является надежной методикой академических исследований.
Было сказано, что...
1) Классы (загружаемые загрузчиками классов) помещаются в специальную область в куче: Permanent Generation.
AFAIK, да. (Обновление: см. Ниже.)
2) Вся информация, относящаяся к классу, такая как имя класса, массивы объектов, связанные с классом, внутренние объекты, используемые JVM (например, java/lang/Object) и информация об оптимизации, попадает в область постоянного создания.
Более или менее да. Я не уверен, что вы подразумеваете под некоторыми из этих вещей. Я предполагаю, что "внутренние объекты, используемые JVM (например, java/lang/Object)", означают дескрипторы внутренних классов JVM.
3) Все статические переменные-члены снова сохраняются в области постоянной генерации.
Сами переменные да. Эти переменные (как и все переменные Java) будут содержать либо примитивные значения, либо ссылки на объекты. Однако, хотя статические переменные-члены находятся в кадре, который размещен в куче permgen, объекты / массивы, на которые ссылаются эти переменные, могут быть размещены в любой куче.
4) Объекты уходят в другую кучу: молодое поколение
Не обязательно. Крупные объекты могут быть выделены непосредственно в арендуемом поколении.
5) В каждом классе есть только одна копия каждого метода, будь то метод статический или нестатический. Эта копия помещается в область постоянного поколения.
Если предположить, что вы ссылаетесь на код метода, то AFAIK да. Это может быть немного сложнее, хотя. Например, этот код может существовать в байт-коде и / или в формах собственного кода в разное время в течение жизни JVM.
... Для нестатических методов все параметры и локальные переменные попадают в стек - и всякий раз, когда происходит конкретный вызов этого метода, мы получаем новый кадр стека, связанный с ним.
Да.
... Я не уверен, где хранятся локальные переменные статического метода. Они в куче постоянного поколения? Или просто их ссылка хранится в области постоянного поколения, а фактическая копия находится где-то еще (где?)
Нет. Они хранятся в стеке, как локальные переменные в нестатических методах.
6) Я также не уверен, где хранится возвращаемый тип метода.
Если вы имеете в виду значение, возвращаемое (не пустым) вызовом метода, то оно возвращается либо в стеке, либо в машинном регистре. Если он возвращается в стеке, это займет 1 или два слова, в зависимости от типа возвращаемого значения.
7) Если объектам (в молодом поколении) необходимо использовать статический элемент (в постоянном поколении), им дается ссылка на статический член &&, им достаточно места в памяти для хранения возвращаемого типа метода и т. Д.,
Это неточно (или, по крайней мере, вы не выражаете себя ясно).
Если какой-либо метод обращается к статической переменной-члену, он получает либо примитивное значение, либо ссылку на объект. Это может быть назначено (существующей) локальной переменной или параметру, назначено (существующему) статическому или нестатическому элементу, назначено (существующему) элементу ранее выделенного массива или просто использовано и отброшено.
Ни в коем случае не нужно выделять новое хранилище для хранения либо ссылки, либо примитива.
Как правило, одно слово памяти - это все, что необходимо для хранения ссылки на объект или массив, а примитивное значение обычно занимает одно или два слова, в зависимости от аппаратной архитектуры.
Ни в коем случае пространство не должно выделяться вызывающей стороной для хранения какого-либо объекта / массива, возвращаемого методом. В Java объекты и массивы всегда возвращаются с использованием семантики передачи по значению... но возвращаемое значение является ссылкой на объект или массив.
ОБНОВИТЬ
Начиная с Java 8 пространство PermGen было заменено на Metaspace. Для получения дополнительной информации, пожалуйста, обратитесь к этим ресурсам: