2016-04-27 7 views
17

Приложение Java запускается с одной кучей для всех потоков. Каждый поток имеет свой собственный стек.Как Java (JVM) выделяет стек для каждого потока

При запуске приложения Java мы используем опцию JVM -Xms и -Xmx для управления размером кучи и -Xss для управления размером стека.

Мое понимание заключается в том, что создаваемая куча становится «управляемой» памятью JVM, и все создаваемые объекты помещаются туда.

Но как работает создание стека? Создает ли Java стек для каждого потока при его создании? Если да, то где именно стек находится в памяти? Это, конечно, не в «управляемой» куче.

Создает ли JVM стек из собственной памяти или предварительно выделяет раздел управляемой области памяти для стека? Если да, то как JVM знает, как могут быть созданы потоки?

+1

Вы можете найти [этот ответ] (http://stackoverflow.com/a/25318740/2032064) interresting – Mifeet

ответ

4

JVM использует больше памяти, чем просто кучу. Например, методы Java, стеки потоков и собственные дескрипторы выделяются в памяти отдельно от кучи, а также внутренних структур данных JVM.

Further reading.

Так, чтобы ответить на ваши вопросы:

ли Java создать стек для каждого потока при его создании?

Да.

Если да, то где именно стек находится в памяти?

В JVM выделяется память, но не на кучу.

Если да, то как JVM знает, как могут быть созданы потоки?

Это не так.

Вы можете создать столько, сколько вы хотите, пока вы не увеличившихся памяти виртуальной машины Java и получить

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread 

EDIT:

Все вышеперечисленное относится к JVM, хотя я считаю, трудно поверить, что другие JVM будут отличаться по таким фундаментальным вопросам.

+0

Кроме того, хотя это хорошие ответы, это внутренняя спецификация для JVM. Любое из вышеперечисленных может измениться в любое время. Он не должен и не имеет значения, как * JVM выполняет свою работу. Пусть JVM решит, как лучше всего управлять своими ресурсами. – markspace

+0

Да, но это не значит узнать, как HotSpot делает это не интересно. – Mifeet

+0

@markspace спасибо, обновил мой ответ с помощью конкретного JVM, но вы действительно думаете, что есть 'JVM', которые действуют по-другому по этим вопросам? – Daniel

30

Есть несколько вещей о потоках, которые Java specification сообщает нам. В числе прочего:

  • Каждый поток виртуальной машины Java имеет собственный стек виртуальной машины Java, созданный одновременно с потоком.

  • Поскольку стек виртуальной машины Java никогда не управляется напрямую, кроме как для push и pop frames, фреймы могут быть выделены в кучу. Память для стека виртуальной машины Java не обязательно должна быть смежной.

  • Спецификация разрешает стек виртуальной машины Java либо иметь фиксированный размер, либо динамически расширять и сжимать, как требуется при вычислении.

Теперь, если мы сосредоточимся на реализациях JVM, таких как HotSpot, мы сможем получить дополнительную информацию. Вот несколько фактов, которые я собрал из разных источников:

  • Минимальный размер стека в HotSpot для потока, по-видимому, исправлен. Это то, для чего предназначен вышеупомянутый вариант -Xss. (Source)

В Java SE 6, по умолчанию на Sparc является 512k в 32-битной виртуальной машины, и 1024k в 64-битной VM. ... Вы можете уменьшить размер стека, выполнив опцию -Xss. ... 64k - это наименьшее количество пространства стека, разрешенного для потока.

  • JRockit выделяет память отдельной из кучи, где стеки расположены. (Source)

Обратите внимание, что JVM использует больше памяти, чем просто кучу. Например, Java-методы, стеки потоков и собственные дескрипторы выделяются в памяти отдельно от кучи, а также внутренние структуры данных JVM.

  • Существует прямое отображение между Thread Java и родной Thread OS в HotSpot. (Source).

  • Но стек потоков Java в HotSpot управляется программным обеспечением, он не является собственным потоковым потоком ОС. (Source)

Он использует отдельный стек программного обеспечения для передачи Java аргументов, в то время как родной стек C используются самой VM. Ряд внутренних переменных JVM, таких как счетчик программ или указатель стека для потока Java, хранятся в переменных C, которые не гарантируются всегда в аппаратных регистрах. Управление этими структурами интерпретатора программного обеспечения потребляет значительную долю от общего времени выполнения.

  • виртуальная машина Java также использует тот же стек Java-поток для нативных методов и JVM во время выполнения вызовов (например, класс нагрузка). (Source).

  • Интересно, что даже выделенные объекты иногда могут быть помещены в стек вместо кучи в качестве оптимизации производительности.(Source)

JVMs можно использовать метод, называемый анализ побега, с помощью которого они могут сказать, что некоторые объекты остаются ограничивается одной нитью на протяжении всей своей жизни, и что жизнь ограничена временем жизни данного пакета Рамка. Такие объекты можно безопасно выделить в стеке вместо кучи.

И потому, что изображение стоит тысячи слов, вот один из James BloomJava memory


Теперь отвечая на некоторые вопросы:

Как JVM знает, как может нити будет быть создан?

Это не так. Легко доказывается противоречием, создавая переменное количество потоков. Он делает некоторые предположения о максимальном количестве потоков и размере стека каждого потока. Вот почему у вас может быть нехватка памяти (а не память кучи памяти!), Если вы выделяете слишком много потоков.

Является ли Java созданием стека для каждого потока при его создании?

Как уже упоминалось, каждый поток виртуальной машины Java имеет собственный стек виртуальной машины Java, созданный одновременно с потоком.(Source).

Если да, то где именно стек находится в памяти? Это, конечно, не в «управляемой» куче.

Как указано выше, Java specification позволяет хранить память стека на куче, технически говоря. Но по крайней мере JRockit JVM использует другую часть памяти.

Создает ли JVM стек из собственной памяти или предварительно выделяет раздел области управляемой памяти для стека?

Стек JVM удалось, поскольку спецификация Java prescribes, как он должен себя вести: A Java Virtual Machine стек хранит кадры (§2.6). Стек виртуальной машины Java аналогичен стеку обычного языка. Одним из исключений являются стеки Native Method, используемые для методов native. Подробнее об этом еще раз в the specification.

+1

Ну, большинство из этого определено в [Спецификация JVM] (https://docs.oracle.com/javase/specs/jvms/se8/html/), нет? AFAIK, GC - это область, которая не учитывается в спецификации. –

+1

Вы правы, в спецификации JVM есть больше, чем я думал. Я обновил свой ответ тем временем. – Mifeet

+0

Итак, если у меня есть куча 512 МБ, и если я создаю 1000 потоков (очевидно, это больше, чем 512 МБ), она занимает память моей кучи и, следовательно, исключение OOM или дополнительное пространство памяти в os? – Jaskey

Смежные вопросы