Який розмір стека за замовчуванням, чи може він зростати, як це працює зі збиранням сміття?


77

Я розумію, що кожна нитка має свою stack. Первісні типи та посилання зберігаються в стеку, а жоден об’єкт не зберігається в стеку.

Мої запитання:

  • Скільки може рости стек? (як з параметрами - Xmsі - Xmx)
  • Чи можемо ми обмежити його зростання?
  • Чи має стек мінімальне і максимальне значення за замовчуванням?
  • Як працює вивіз сміття на стеку?

лише невелике зауваження для людей, які читають це: Escape-Analysis (Java 6 Update 21 і вище) дозволяє зберігати об'єкти в стеку. Менше роботи для збирача сміття.
miracle_the_V


GC не працює на стеку. Ви не можете створювати речі в стеку, тому збирати нічого - JVM сама кладе речі в стек і за потреби видаляє їх. «Сміття», яке збирається, - це екземпляри ваших об’єктів, які ви створили.
mvmn

Відповіді:


94

Скільки може рости стек?

Ви можете скористатися опцією VM з назвою, ssщоб відрегулювати максимальний розмір стека. Опція VM зазвичай передається за допомогою -X {option}. Таким чином, ви можете використовувати java -Xss1Mдля встановлення максимального розміру стека 1M.

Кожна нитка має принаймні один стек. Деякі віртуальні машини Java (JVM) поміщають стек Java (виклики методів Java) і власний стек (виклики власного методу у VM) в один стек і виконують розмотування стека за допомогою керованого до власного кадру, відомого як M2NFrame. Деякі JVM тримають два стеки окремо. У Xssбільшості випадків встановлюється розмір стеку Java.

Для багатьох JVM вони встановлюють різні значення за замовчуванням для розміру стека на різних платформах.

Чи можемо ми обмежити це зростання?

Коли відбувається виклик методу, на стеку цього потоку буде створений новий кадр стека. Стек буде містити локальні змінні, параметри, адресу повернення тощо. У Java ви ніколи не можете помістити об'єкт у стек, у стеку може зберігатися лише посилання на об'єкт. Оскільки масив також є об'єктом у Java, масиви також не зберігаються в стеку. Отже, якщо ви зменшите кількість локальних примітивних змінних, параметрів, згрупувавши їх в об'єкти, ви зможете зменшити простір у стеку. Насправді той факт, що ми не можемо явно помістити об'єкти в стек Java, впливає на продуктивність деякий час (промах кешу).

Чи має стек якесь мінімальне значення за замовчуванням чи максимальне значення за замовчуванням?

Як я вже говорив раніше, різні віртуальні машини відрізняються і можуть змінюватися залежно від версії. Дивіться тут .

як працює збирання сміття у стеку?

Збір сміття на Java - гаряча тема. Вивіз сміття має на меті збирати недоступні предмети в купі . Тож для цього потрібне визначення поняття „досяжний”. Все, що знаходиться в стеку, є частиною посилань на кореневий набір у GC. Все, до чого можна дістатись із кожного стека кожного потоку, слід розглядати як живе. Є деякі інші посилання на кореневі набори, такі як об’єкти Thread та деякі об’єкти класу.

Це лише дуже туманне використання стека на GC. В даний час більшість JVM використовують поколінні ГХ. У цій статті подано короткий вступ про Java GC. А нещодавно я прочитав дуже гарну статтю, яка розповідає про GC на .net. GC на oracle jvm досить схожий, тому я думаю, що це також може вам допомогти.


5
Хороша відповідь. Я хотів би лише додати, що я вважаю за замовчуванням консервативні, і вони призначені для охоплення всіх видів розгортань. Але на моєму досвіді, навіть із великими програмами (понад 500 тис. Рядків коду), що працюють на серверах додатків, я ніколи не мав помилки StackOverflow, навіть якщо стек встановлений на 256 тис. (-Xss256k). Розглянемо сервер додатків із 70 запущеними потоками зі стеком 1 МБ за замовчуванням, це додаткові 70 МБ для процесу.
brettw

6
java -Xss 100M -jar testing.jarвиникла помилка "Неправильний розмір стека потоку: -Xss Помилка: Не вдалося створити віртуальну машину Java." але java -Xss100M -jar testing.jarпрацював просто чудово. Запуск Windows 10 64-розрядної версії з Java "1.8.0_112". Чи слід редагувати вашу публікацію, щоб прибрати місце?
Аарон Франке

Для людей, які використовують maven, це виглядає так: gist.github.com/belkacemlahouel/…
belka

1
"У Java ви ніколи не можете помістити об'єкт у стек ... впливає на продуктивність" Це неправда! HotSpot розподіляє об'єкти у стеку, якщо аналіз екранування доводить, що вони недоступні ніде. Це покращує локалізацію кеш-пам'яті, але тим більше економить на витратах GC. Це є основною причиною відмінної роботи Java.
Олександр Дубінський

13

Як ви говорите, локальні змінні та посилання зберігаються у стеку. Коли метод повертається, вказівник стека просто переміщується туди, де він був до запуску методу, тобто всі локальні дані "видаляються зі стеку". Тому в стеку не потрібно збирати сміття, це відбувається лише в купі.

Щоб відповісти на ваші конкретні запитання:

  • Дивіться це питання про те, як збільшити розмір стека.
  • Ви можете обмежити зростання стека, виконавши:
    • групування багатьох локальних змінних в об'єкті: цей об'єкт зберігатиметься в купі, а в стеку зберігатиметься лише посилання
    • обмежити кількість викликів вкладених функцій (як правило, не використовуючи рекурсію)
  • Для Windows розмір стека за замовчуванням становить 320 тис. Для 32-бітних та 1024 тис. Для 64-бітних, див. Це посилання .

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

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