Память в JVM
Как ты уже знаешь, JVM запускает Java-программы внутри себя. Как и любая виртуальная машина, она имеет собственную систему организации памяти.
Схема организации внутренней памяти указывает на принцип работы вашего Java-приложения. Таким образом можно определить узкие места в работе приложений и алгоритмов. Давай разберемся, как она устроена.
Важно! Модель Java в первоначальном виде была недостаточно хороша, поэтому она была пересмотрена в Java 1.5. Эта версия используется по сей день (Java 14+).
Стек потока
Модель памяти в Java, используемая внутри JVM, делит память на стеки потоков (thread stacks) и кучу (heap). Посмотрим на Java-модель памяти, логично разделенную на блоки:
Все потоки, работающие в JVM, имеют свой стек. Стек в свою очередь держит информацию о том, какие методы вызвал поток. Я буду называть это “стеком вызовов”. Стек вызовов возобновляется, как только поток выполняет свой код.
Стек потока содержит в себе все локальные переменные, требующиеся для выполнения методов из стека потока. Поток может получить доступ только к своему стеку. Локальные переменные не видны остальным потокам, только потоку, создавшему их. В ситуации, когда два потока выполняют один и тот же код, они оба создают свои локальные переменные. Таким образом, каждый поток имеет свою версию каждой локальной переменной.
Все локальные переменные примитивных типов ( boolean , byte , short , char , int , long , float , double ) полностью хранятся в стеке потоков и не видны другим потокам. Один поток может передать копию примитивной переменной другому потоку, но не может совместно использовать примитивную локальную переменную.
Куча (heap)
Куча содержит все объекты, созданные в вашем приложении, независимо от того, какой поток создал объект. К этому относятся и обертки примитивных типов (например, Byte , Integer , Long и так далее). Неважно, был ли объект создан и присвоен локальной переменной или создан как переменная-член другого объекта, он хранится в куче.
Ниже диаграмма, которая иллюстрирует стек вызовов и локальные переменные (они хранятся в стеках), а также объекты (они хранятся в куче):
В случае, когда локальная переменная примитивного типа, она хранится в стеке потока.
Локальная переменная также может быть ссылкой на объект. В этом случае ссылка (локальная переменная) хранится в стеке потоков, но сам объект хранится в куче.
Объект содержит методы, эти методы содержат локальные переменные. Эти локальные переменные также хранятся в стеке потоков, даже если объект, которому принадлежит метод, хранится в куче.
Переменные-члены объекта хранятся в куче вместе с самим объектом. Это верно как в случае, когда переменная-член имеет примитивный тип, так и в том случае, если она является ссылкой на объект.
Статические переменные класса также хранятся в куче вместе с определением класса.
Взаимодействие с объектами
К объектам в куче могут обращаться все потоки, которые имеют ссылку на объект. Если поток имеет доступ к объекту, то он может получить доступ к переменным этого объекта. Если два потока вызывают метод для одного и того же объекта одновременно, они оба будут иметь доступ к переменным-членам объекта, но каждый поток будет иметь свою собственную копию локальных переменных.
Два потока имеют набор локальных переменных. Local Variable 2 указывает на общий объект в куче ( Object 3 ). Каждый из потоков имеет свою копию локальной переменной со своей ссылкой. Их ссылки являются локальными переменными и поэтому хранятся в стеках потоков. Тем не менее, две разные ссылки указывают на один и тот же объект в куче.
Обрати внимание, что общий Object 3 имеет ссылки на Object 2 и Object 4 как переменные-члены (показано стрелками). Через эти ссылки два потока могут получить доступ к Object 2 и Object 4.
На диаграмме также показана локальная переменная ( Local variable 1 из methodTwo ). Каждая ее копия содержит разные ссылки, которые указывают на два разных объекта ( Object 1 и Object 5 ), а не на один и тот же. Теоретически оба потока могут обращаться как к Object 1 , так и к Object 5 , если они имеют ссылки на оба этих объекта. Но на диаграмме выше каждый поток имеет ссылку только на один из двух объектов.
Пример взаимодействия с объектами
Давай посмотрим, как мы можем продемонстрировать работу в коде:
public class MySomeRunnable implements Runnable() < public void run() < one(); >public void one() < int localOne = 1; Shared localTwo = Shared.instance; //… делаем что-то с локальными переменными two(); >public void two() < Integer localOne = 2; //… делаем что-то с локальными переменными >>
Метод run() вызывает метод one() , а one() в свою очередь вызывает two() .
Метод one() объявляет примитивную локальную переменную ( localOne ) типа int и локальную переменную ( localTwo ), которая является ссылкой на объект.
Каждый поток, выполняющий метод one() , создаст свою собственную копию localOne и localTwo в своем стеке. Переменные localOne будут полностью отделены друг от друга, находясь в стеке каждого потока. Один поток не может видеть, какие изменения вносит другой поток в свою копию localOne .
Каждый поток, выполняющий метод one() , также создает свою собственную копию localTwo . Однако две разные копии localTwo в конечном итоге указывают на один и тот же объект в куче. Дело в том, что localTwo указывает на объект, на который ссылается статическая переменная instance . Существует только одна копия статической переменной, и эта копия хранится в куче.
Таким образом, обе копии localTwo в конечном итоге указывают на один и тот же экземпляр Shared . Экземпляр Shared также хранится в куче. Он соответствует Object 3 на диаграмме выше.
Обрати внимание, что класс Shared также содержит две переменные-члены. Сами переменные-члены хранятся в куче вместе с объектом. Две переменные-члены указывают на два других объекта Integer . Эти целочисленные объекты соответствуют Object 2 и Object 4 на диаграмме.
Также обрати внимание, что метод two() создает локальную переменную с именем localOne . Эта локальная переменная является ссылкой на объект типа Integer . Метод устанавливает ссылку localOne для указания на новый экземпляр Integer . Ссылка будет храниться в своей копии localOne для каждого потока. Два экземпляра Integer будут сохранены в куче и, поскольку метод создает новый объект Integer при каждом выполнении, два потока, выполняющие этот метод, будут создавать отдельные экземпляры Integer . Они соответствуют Object 1 и Object 5 на диаграмме выше.
Обрати также внимание на две переменные-члены в классе Shared типа Integer , который является примитивным типом. Поскольку эти переменные являются переменными-членами, они все еще хранятся в куче вместе с объектом. В стеке потоков хранятся только локальные переменные.
Русские Блоги
[Вопросы интервью Java] Объясните использование стеков (стек), кучи (куча) и статических областей хранения в памяти
Вопросы на интервью Java: Объясните использование стеков, стеков, кучей и статических областей хранения в памяти
Область дакала: экземпляры, специально используемые для сохранения объектов (объекты и массив, созданные новыми), фактически, только сохраняют значения атрибута экземпляра объекта, тип атрибутов и тип самого объекта. Инструкция, хранящаяся в куча)
1. Все хранилище - это объект, каждый объект содержит один, соответствующий емуКлассная информация.(Цель класса - получить инструкцию по эксплуатации) 2. JVM имеет только одну куча(heap) Его разделяют все потоки, а основные типы и ссылки на объекты не хранятся в куче. Только сам объект. 3. Обычно он распределяется и выпускается программистами. Если программист не выпущен, программа может быть восстановлена ОС в конце программы.
Область стека: После того, как экземпляр объекта выделен в куче, вам необходимо сохранить 4 -лабютный адрес памяти кучи в стеке, чтобы найти положение экземпляра объекта в куче, чтобы экземпляр объекта был легко найти.
1. Каждый поток содержит область стека, которая сохраняет только объект основного типа данных и ссылку на пользовательский объект(Не объект), Объекты хранятся в области свай 2. Данные в каждом стеке(Примитивный тип и цитата объекта) Все они частные, а другие стеки не могут быть доступны. 3. Стек разделен на3 части: зона переменной базового типа, контекст среды выполнения, область инструкции по эксплуатации(Инструкции по эксплуатации магазина)。 4. Автоматически распределять и выпустить компилятором, значение параметра функции, значение локальной переменной и т. Д.
Статическая область/область метода:
1. Область метода также называется статической областью. Как и куча, ее разделяют все потоки. МЕТОДА ЗАЛАНГА ВСЕКласс иСтатическая переменная. 2. Область метода содержит единственный элемент, который постоянно во всей программе, такой какclass,Статическая переменная.
3. Статическая константа хранится в постоянной области области метода, и статическая константа не может быть изменена после инициализации.
Стек и стек — ключ к запуску программы, и это следует четко понятно.
Стек представляет собой устройство при выполнении, а куча — это устройство во время хранения.
В куче есть объект. Стек имеет ссылку на основной тип данных и объект в куче. Размер объекта неоценим, или его можно динамически изменено, но в стеке объект соответствует только ссылке на 4BTYE (преимущества разделения стека).
Зачем различать кучу от стека? Могу ли я сохранить данные в стеке?
Во -первых, с точки зрения дизайна программного обеспечения стек представляет логику обработки, а куча представляет данные. Это отдельное делает логику обработки более ясной. Мысли, которые разделены. Эта изоляция и модульная мысль отражаются во всех аспектах дизайна программного обеспечения.
Во -вторых, разделение кучи и стека позволяет делиться содержанием кучи несколькими стеками (это также можно понять, когда несколько потоков получают доступ к одному и тому же объекту). Есть много таких общих преимуществ. С одной стороны, этот совместный обмен обеспечивает эффективное взаимодействие с данными (например: общая память). С другой стороны, постоянная обмена и кэш в куче может быть доступен во всех стеках, сохранение пространства.
В -третьих, из -за потребностей стека, таких как сохранение контекста работы системы, необходимо разделить сегмент адреса. Поскольку стек может расти только вверх, он ограничит способность хранить содержание стека. Различные в куче, объекты в куче могут расти динамически по мере необходимости. Следовательно, разделение стека и кучи делает возможным динамический рост. В соответствующем стеке есть только адрес для записи адреса в куче.
В -четвертых, объект -ориентированный является идеальным комбинацией кучи и стека. На самом деле, нет никакой разницы между программой -ориентированной объектом и предыдущей структурированной программой. Тем не менее, объектно -ориентированное введение изменило образ мышления о проблемах и ближе к естественному мышлению. Когда мы разбираем объект, вы обнаружите, что атрибуты объекта на самом деле являются данными, хранящиеся в куче; и поведение (метод) объекта является рабочей логикой, помещенной в стек. Когда мы пишем объект, мы фактически пишем структуру данных и логику данных обработки. Я должен признать, что дизайн, ориентированный на объект, действительно красивый.