Где живут методы? Стек или в куче? - PullRequest
4 голосов
/ 30 июля 2009

Я знаю, что локальные переменные и параметры методов живут в стеке, но я не могу понять, где на самом деле находятся методы в случае Java?

Если я объявлю какой-либо объект Thread, например:

Thread t=new Thread();
t.start();

Таким образом, это означает, что я создал отдельный вызов методов помимо основного метода. Что это значит? Означает ли это вызов отдельной последовательности методов из памяти стека? Я прав?

Ответы [ 6 ]

8 голосов
/ 30 июля 2009

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

Для (плохого) представления ASCII:

-------
|STACK|
-------
|FREE |
-------
|HEAP |
-------
|CODE |
-------

Где STACK представляет стек, FREE представляет свободную память, HEAP представляет кучу, а CODE представляет пространство кода.

Это то, что говорит моя память - некоторые детали могут быть неправильными.

8 голосов
/ 30 июля 2009

Каждому потоку выделяется свой собственный стек.

В этой статье содержится хорошее введение в разделение памяти в процессе Java.

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

Я видел много сценариев, когда клиенты реализовывали многопоточные серверы на основе того, что каждый поток делает очень мало, и у них возникают проблемы с памятью. Это потому, что каждому потоку выделяется свой стек, и это (очевидно) складывается. Я думаю значение по умолчанию - 512 КБ на поток, но я не нашел канонического источника для этого.

6 голосов
/ 30 июля 2009

Стек состоит из вызовов методов. То, что java помещает в стек, - это запись вызова метода, которая инкапсулирует все переменные (как параметры, так и локально созданные экземпляры переменных) для этого метода. Когда вы запускаете приложение Java, единственный метод в стеке - главный метод (который автоматически включает параметр args):

main(args)

Когда говорят, что вы создаете объект Foo и вызываете foo.method (), стек теперь выглядит так:

method()
main(args)

Когда методы вызываются, они помещаются в стек, а когда они возвращаются, они удаляются или «выталкиваются» из стека. Поскольку переменные объявляются и используются, запись стека, соответствующая текущему методу (в верхней части стека), увеличивается с учетом размера переменной.

Для вашего примера с потоками каждый поток будет иметь свой собственный стек, который существует независимо от стека каждого другого потока.

1 голос
/ 30 июля 2009

Куча разбита на несколько поколений.

Байт-код и соответствующий ему JIT-скомпилированный машинный код живут в так называемой постоянной генерации вместе с интернированными строками и другими данными класса.

Несмотря на то, что это называется "постоянным" поколением, оно все равно может быть собрано мусором. Некоторые библиотеки, фреймворки и языки JVM генерируют байт-код во время выполнения, поэтому постоянное поколение иногда нуждается в очистке. Точно так же как другие поколения кучи, но (обычно надеются) реже.

1 голос
/ 30 июля 2009

Стек содержит все локальные переменные и все активные вызовы методов. В куче хранится все остальное.

Что касается вашего подвопроса: это означает, что новый стек создается с собственной выделенной памятью. В то время как ваш новый поток будет использовать общее пространство кучи (памяти), выделенное jvm

0 голосов
/ 30 июля 2009

Фактический байт-код и / или JIT-код будет находиться в памяти процесса. Вероятно, в памяти процесса будет только одна его копия, поскольку все потоки в данном процессе совместно используют эту память. Любые переменные shared для этих потоков будут доступны общим методам. Переменные, локальные для потоков (даже локальные переменные метода, используемые в потоке), будут созданы в памяти этого потока.

...