2009-07-30 2 views
4

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

Если я объявляю любой объект Thread, как:

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

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

+3

То, как вы это формулируете, заставляет меня чувствовать себя некомфортно. «Метод» «Живет» в кодовом пространстве. Это не в стеке или куче. Объект создается в куче, которая имеет указатель для каждого из своих методов. Этот объект живет в куче, но методы, на которые он указывает, находятся в коде. –

ответ

8

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

This article имеет хорошее представление о разделении памяти в процессе Java.

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

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

8

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

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

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

Если СТЕК представляет собой стек, FREE представляет собой свободную память, КУЧА представляет собой кучу, а код представляет кодовое пространство.

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

+0

Как отметил Брайан Агнью, каждый процесс имеет собственный стек, в то время как они разделяют кучу. – aperkins

1

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

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

+0

Я уверен, что стек содержит все локальные ** примитивные ** переменные и указатели (ну, действительно, ссылки) на фактические объекты. – sixtyfootersdude

0

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

1

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

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

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

6

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

main(args) 

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

method() 
main(args) 

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

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