статичний розподіл у Java - купа, стек та постійне покоління


117

Я останнім часом багато читав про схеми розподілу пам’яті в Java, і було багато сумнівів, коли я читав з різних джерел. Я зібрав свої концепції, і просив би пройти всі пункти і прокоментувати їх. Я дізнався, що розподіл пам’яті є специфічним для JVM, тому я повинен заздалегідь сказати, що моє запитання не є конкретним.

  1. Заняття (завантажені навантажувачами) проходять у купі на спеціальній ділянці: Постійне покоління
  2. Вся інформація, що стосується такого класу, як назва класу, масиви об'єктів, пов'язані з класом, внутрішні об'єкти, що використовуються JVM (наприклад, java / lang / Object), та інформація про оптимізацію надходить у область постійного покоління.
  3. Всі змінні статичних членів знову зберігаються в області постійного покоління.
  4. Об'єкти йдуть на різній купі: Молоде покоління
  5. Існує лише одна копія кожного методу в класі, будь то метод статичний або нестатичний. Цей примірник розміщується в області постійного покоління Для нестатичних методів всі параметри та локальні змінні переходять на стек - і коли є конкретний виклик цього методу, ми отримуємо новий кадр стека, пов'язаний з ним. Я не впевнений, де зберігаються локальні змінні статичного методу. Вони на купі постійного покоління? Або просто їх посилання зберігаються в області Постійного покоління, а фактична копія десь в іншому місці (Де?)
  6. Я також не впевнений, де зберігається тип повернення методу.
  7. Якщо об'єктам (у молодому поколінні) потрібно використовувати статичний член (у постійному поколінні), їм надається посилання на статичний член &&, їм надається достатньо місця в пам'яті для зберігання типу повернення методу тощо.

Дякую, що ви пройшли це!

Відповіді:


152

По-перше, як вам має бути зрозуміло на даний момент, дуже мало людей, які можуть підтвердити ці відповіді з перших знань. Дуже мало людей працювали над останніми JVM HotSpot або вивчали їх на глибину, необхідну для того, щоб дійсно знати. Більшість людей тут (включаючи мене) відповідають на основі того, що вони бачили, написаного в іншому місці, або того, що вони зробили. Зазвичай те, що написано тут, або в різних статтях та веб-сторінках, базується на інших джерелах, які можуть бути, а можуть і не бути остаточними. Часто це спрощене, неточне або просто невірно.

Якщо ви хочете остаточно підтвердити свої відповіді, вам дійсно потрібно завантажити вихідний код OpenJDK ... і зробити власне дослідження , прочитавши та зрозумівши вихідний код. Задавати питання щодо ПЗ або ловити через випадкові статті в Інтернеті не є надійною академічною методикою дослідження.

Сказавши, що ...

... моє запитання є специфічним для ВС.

У той час, коли це питання було задано, Sun Microsystems припинила своє існування. Тому питання було специфічним для Oracle. AFAIK, усі поточні (не дослідницькі) сторонні JVM-реалізації є або прямими портами випуску OpenJDK, або походять з іншого випуску Sun / Oracle.

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

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

До Java 8, так.

Як і в Java 8, простір PermGen було замінено на Metaspace. Завантажені та складені JIT класи зараз ходять туди. PermGen більше не існує.

2) Вся інформація, що стосується такого класу, як назва класу, масиви об'єктів, пов'язані з класом, внутрішні об'єкти, що використовуються JVM (наприклад, java / lang / Object), та інформація про оптимізацію надходить у область постійного покоління.

Більше чи менше, так. Я не впевнений, що ви маєте на увазі під цими речами. Я здогадуюсь, що "внутрішні об'єкти, що використовуються JVM (наприклад, java / lang / Object)" означає дескриптори класу JVM-внутрішнього класу.

3) Усі змінні статичних членів знову зберігаються в області постійного покоління.

Самі змінні так. Ці змінні (як і всі змінні Java) містять або примітивні значення, або посилання на об'єкти. Однак, хоча змінні статичних членів знаходяться у кадрі, виділеному в купі permgen, об'єкти / масиви, на які посилаються ці змінні, можуть бути розподілені в будь-якій купі.

4) Об'єкти йдуть на різній купі: Молоде покоління

Не обов'язково. Великі об'єкти можуть бути виділені безпосередньо в покоління, що працює на стажуванні.

5) Існує лише одна копія кожного методу в класі, будь то метод статичний або нестатичний. Цей примірник розміщується в області постійного покоління

Якщо припустити, що ви посилаєтесь на код методу, то AFAIK так. Це може бути дещо складніше. Наприклад, цей код може існувати у байт-кодах та / або нативних кодових формах у різний час протягом життя JVM.

... Для нестатичних методів усі параметри та локальні змінні переходять у стек - і кожного разу, коли є конкретний виклик цього методу, ми отримуємо новий кадр стека, пов'язаний з ним.

Так.

... Я не впевнений, де зберігаються локальні змінні статичного методу. Вони на купі постійного покоління? Або просто їх посилання зберігаються в області Постійного покоління, а фактична копія десь в іншому місці (Де?)

Ні. Вони зберігаються в стеці, як і локальні змінні в нестатичних методах.

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

Якщо ви маєте на увазі значення, повернене викликом методу (недійсним), воно або повертається в стеці, або в машинному реєстрі. Якщо він повертається на стек, для цього потрібно 1 або два слова, залежно від типу повернення.

7) Якщо об'єкти (у молодому поколінні) потребують використання статичного елемента (у постійному поколінні), їм надається посилання на статичний член &&, їм надається достатньо місця в пам'яті для зберігання типу повернення методу тощо .

Це неточно (або, принаймні, ви не висловлюєте себе чітко).

Якщо деякий метод отримує доступ до статичної змінної члена, то воно отримує або примітивне значення, або посилання на об'єкт . Це може бути присвоєно (існуючій) локальній змінній або параметру, призначеному (існуючому) статичному або нестатичному члену, призначеному (існуючому) елементу раніше виділеного масиву, або просто використаному та відкинутому.

  • Ні в якому разі не потрібно виділяти нове сховище, яке б містило посилання або примітивне значення.

  • Зазвичай одне слово пам'яті - це все, що потрібно для зберігання посилання на об'єкт або масив, а примітивне значення зазвичай займає одне або два слова, залежно від архітектури обладнання.

  • Ні в якому разі не потрібно виділяти простір абоненту, щоб утримувати якийсь об'єкт / масив, повернутий методом. У Java об'єкти та масиви завжди повертаються за допомогою семантики прохідних значень ... але це значення, яке повертається, є посиланням на об'єкт або масив.


Для отримання додаткової інформації зверніться до цих ресурсів:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.