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


117

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

  1. Классы (загруженные загрузчиками классов) помещаются в специальную область в куче: Permanent Generation
  2. Вся информация, относящаяся к классу, такая как имя класса, массивы объектов, связанные с классом, внутренние объекты, используемые JVM (например, java / lang / Object), и информация об оптимизации, попадает в область постоянного создания.
  3. Все статические переменные-члены снова сохраняются в области постоянного поколения.
  4. Объекты ложатся в другую кучу: Молодое поколение
  5. Для каждого класса существует только одна копия каждого метода, будь то статический или нестатический метод. Эта копия помещается в область постоянного поколения. Для нестатических методов все параметры и локальные переменные помещаются в стек - и всякий раз, когда происходит конкретный вызов этого метода, мы получаем новый связанный с ним стек-фрейм. Я не уверен, где хранятся локальные переменные статического метода. Находятся ли они в куче постоянного поколения? Или просто их ссылка хранится в области постоянного поколения, а фактическая копия находится в другом месте (где?)
  6. Я также не уверен, где хранится возвращаемый тип метода.
  7. Если объекты (в молодом поколении) должны использовать статический член (в постоянном поколении), им дается ссылка на статический член &&, им предоставляется достаточно места в памяти для хранения возвращаемого типа метода и т. Д.

Спасибо, что прошли через это!

Ответы:


152

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

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

Было сказано, что ...

... мой вопрос касается Sun.

В то время, когда был задан этот вопрос, Sun Microsystems прекратила свое существование. Следовательно, вопрос был специфическим для Oracle. AFAIK, все текущие (не исследовательские) сторонние реализации JVM являются либо прямыми портами выпуска OpenJDK, либо производными от другого выпуска Sun / Oracle.

Приведенные ниже ответы относятся к выпускам Oracle Hotspot и OpenJDK, а также, вероятно, к большинству других ... включая GraalVM.

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

До Java 8 - да.

Начиная с Java 8, пространство PermGen было заменено на Metaspace. Загруженные и JIT-скомпилированные классы теперь идут туда. PermGen больше не существует.

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

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

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

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

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

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

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

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

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

Да.

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

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

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

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

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

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

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

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

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

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


Для получения дополнительной информации, пожалуйста, обратитесь к этим ресурсам:

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.