что такое runtime data areas
The JVM spec defines certain run-time data areas that are needed during the execution of the program. Some of them are created while the JVM starts up. Others are local to threads and are created only when a thread is created (and destroyed when the thread is destroyed). These are listed below −
PC (Program Counter) Register
It is local to each thread and contains the address of the JVM instruction that the thread is currently executing.
Stack
It is local to each thread and stores parameters, local variables and return addresses during method calls. A StackOverflow error can occur if a thread demands more stack space than is permitted. If the stack is dynamically expandable, it can still throw OutOfMemoryError.
It is shared among all the threads and contains objects, classes’ metadata, arrays, etc., that are created during run-time. It is created when the JVM starts and is destroyed when the JVM shuts down. You can control the amount of heap your JVM demands from the OS using certain flags (more on this later). Care has to be taken not to demand too less or too much of the memory, as it has important performance implications. Further, the GC manages this space and continually removes dead objects to free up the space.
Method Area
This run-time area is common to all threads and is created when the JVM starts up. It stores per-class structures such as the constant pool (more on this later), the code for constructors and methods, method data, etc. The JLS does not specify if this area needs to be garbage collected, and hence, implementations of the JVM may choose to ignore GC. Further, this may or may not expand as per the application’s needs. The JLS does not mandate anything with regard to this.
Run-Time Constant Pool
The JVM maintains a per-class/per-type data structure that acts as the symbol table (one of its many roles) while linking the loaded classes.
Native Method Stacks
When a thread invokes a native method, it enters a new world in which the structures and security restrictions of the Java virtual machine no longer hamper its freedom. A native method can likely access the runtime data areas of the virtual machine (it depends upon the native method interface), but can also do anything else it wants.
Garbage Collection
The JVM manages the entire lifecycle of objects in Java. Once an object is created, the developer need not worry about it anymore. In case the object becomes dead (that is, there is no reference to it anymore), it is ejected from the heap by the GC using one of the many algorithms – serial GC, CMS, G1, etc.
During the GC process, objects are moved in memory. Hence, those objects are not usable while the process is going on. The entire application has to be stopped for the duration of the process. Such pauses are called ‘stop-the-world’ pauses and are a huge overhead. GC algorithms aim primarily to reduce this time. We shall discuss this in great detail in the following chapters.
Thanks to the GC, memory leaks are very rare in Java, but they can happen. We will see in the later chapters how to create a memory leak in Java.
Русские Блоги
JVM Run-Time Data Areas
Run-Time Data Areas
JVM определяет множество различных областей данных времени выполнения для использования во время выполнения программы. Некоторые из них создаются при запуске JVM и уничтожаются при выходе из JVM, другие принадлежат потоку, создаются при его создании и уничтожаются при выходе из него.
Стеки виртуальных машин Java
Как и счетчик ПК, стеки виртуальных машин Java являются частными потоками и создаются при создании потока.
Стек виртуальной машины Java встроен во фрейм. Когда вызывается метод, создается новый кадр стека, и соответствующий кадр стека уничтожается в конце вызова метода (независимо от того, нормально ли выходит метод или нет).
В стеке хранится такая информация, как таблица локальных переменных, стек операций, динамическая ссылка и выход метода текущего метода в классе.
1) Таблица локальных переменных локальных переменных (Local Variable Array)
Размер таблицы локальных переменных определяется во время компиляции. В ней могут храниться логические, char, byte, short, int, double, float, double, reference (указывающие на адрес объекта кучи ) И типы returnAddress (указывающие на адрес инструкции байт-кода), из которых длинные и двойные данные занимают два последовательныхПространство локальной переменной (неизвестный размер), Остальные типы данных занимают только один. Поэтому размер таблицы локальных переменных зависит только от реализации JVM.
Доступ к таблице локальных переменных осуществляется через индекс, а диапазон значений индекса равен [0, array.length).
2)Operand Stacks
Спецификация виртуальной машины Java определяет два исключения для этой области:
StackOverflowError, JVM генерирует StackOverflowError, когда запрос потока превышает глубину, разрешенную стеками JVM.
OutOfMemoryError, если стеки JVM могут быть динамически расширены (фактически, большинство текущих виртуальных машин Java могут динамически расширяться), когда память не может удовлетворить свой запрос на расширение, она не может применяться для достаточного объема памяти JVM выдает ошибку OutOfMemoryError.
Method Area
Область метода используется потоками и хранит информацию о классе, включая пул констант времени выполнения, данные полей и методов, код метода и конструктора и т. Д.
Область метода логически является частью области кучи и может иметь фиксированный размер или динамически расширяться. Область физической памяти не обязательно должна быть смежной. В отличие от кучи, область метода имеет меньше поведения для сборки мусора и может даже не выполнять сборку мусора.
Если область метода не может удовлетворить требования выделения памяти, генерируется исключение OutOfMemoryError.
Run-Time Constant Pool
Пул констант времени выполнения является частью области метода и используется для хранения различных литералов и ссылок на символы, сгенерированных во время компиляции. Это содержимое будет сохранено в пуле констант времени выполнения после загрузки класса. дюйм
Как и в области методов, когда пул констант не может применяться к памяти, генерируется исключение OutOfMemoryError.
Что такое runtime data areas
4 contributors
Users who have contributed to this file
За что отвечает JVM:
JVM работает с 2мя типами данных: примитивные типы (primitive types) и ссылочные типы (reference types).
Примитивы
Типы ссылок и значения
Существует три типа ссылочных типов: типы классов, типы массивов и типы интерфейсов. Их значения являются ссылками на динамически создаваемые экземпляры классов, массивы или экземпляры классов, которые реализуют интерфейсы соответственно.
Загрузчик классов является частью JRE, которая динамически загружает Java классы в JVM. Обычно классы загружаются только по запросу. Система исполнения в Java не должна знать о файлах и файловых системах благодаря загрузчику классов. Делегирование является важной концепцией, которую выполняет загрузчик. Загрузчик классов отвечает за поиск библиотек, чтение их содержимого и загрузку классов, содержащихся в библиотеках. Эта загрузка обычно выполняется «по требованию», поскольку она не происходит до тех пор, пока программа не вызовет класс. Класс с именем может быть загружен только один раз данным загрузчиком классов.
При запуске JVM, используются три загрузчика классов:
Загрузчик классов выполняет три основных действия в строгом порядке:
Пользовательский загрузчик классов
Загрузчик классов написан на Java. Поэтому возможно создать свой собственный загрузчик классов, не понимая тонких деталей JVM. У каждого загрузчика классов Java есть родительский загрузчик классов, определенный при создании экземпляра нового загрузчика классов или в качестве системного загрузчика классов по умолчанию для виртуальной машины.
Что делает возможным следующее:
Области данных времени выполнения
Run-Time Data Areas. JVM выделяет множество областей данных во время выполнения, которые используются во время выполнения программы. Некоторые участки данных созданы JVM во время старта и уничтожаются во время её выключения. Другие создаются для каждого потока и уничтожаются, когда поток уничтожается.
The pc Register (PCR)
Виртуальная машина Java может поддерживать много потоков исполнения одновременно. Каждый поток виртуальной машины Java имеет свой собственный регистр PC (program counter). В любой момент каждый поток виртуальной машины Java выполняет код одного метода, а именно текущий метод для этого потока. Если этот метод не является native, регистр pc содержит адрес инструкции виртуальной машины Java, выполняемой в настоящее время.
Коротко говоря: для одного потока, существует один PCR, который создается при запуске потока. PCR хранит адрес выполняемой сейчас инструкции JVM.
Java Virtual Machine Stacks
Каждый поток в JVM имеет собственный стек, созданный одновременно с потоком. Стек в JVM хранит frames. Cтеки в JVM могут иметь фиксированный размер или динамически расширяться и сжиматься в соответствии с требованиями вычислений.
Heap
Method Area
JVM имеет область методов, которая является общей для всех потоков. Она хранит структуры для каждого класса, такие как пул констант, данные полей и методов, а также код для методов и конструкторов, включая специальные методы, используемые при инициализации классов и экземпляров, и инициализации интерфейса. Хотя область метода является логически частью кучи, простые реализации могут не обрабатываться сборщиком мусора. Область метода может иметь фиксированный размер или может быть расширена в соответствии с требованиями вычислений и может быть сокращена, если большая область метода становится ненужной.
Run-Time Constant Pool
A run-time constant pool существует для каждого класса или интерфейса в рантайме и представленно constant_pool таблицей в *.class файле. Он содержит несколько видов констант: от числовых литералов, известных во время компиляции, до ссылок на методы и поля, которые должны быть разрешены во время выполнения. Сам run-time constant pool выполняет функцию, аналогичную функции таблицы символов для обычного языка программирования, хотя он содержит более широкий диапазон данных, чем типичная таблица символов. Каждый run-time constant pool отделён от JVM’s method area. JVM создаёт run-time constant pool вместе с созданием class или interface.
Native Method Stacks
Реализация виртуальной машины Java может использовать обычные стеки, обычно называемые «стеки Си», для поддержки native methods (методов, написанных на языке, отличном от языка программирования Java).
Frame используется для хранения данных и частичных результатов, а также для выполнения динамического связывания, возврата значений для методов и отправки исключений. Новый frame создается каждый раз, когда вызывается метод. Frame уничтожается, когда завершается вызов метода, является ли это завершение нормальным или резким (он генерирует неперехваченное исключение). Frames выделяются из стека потока, создающего frame. Каждый frame имеет свой собственный массив локальных переменных, свой собственный стек операндов и ссылку на пул констант во время выполнения класса текущего метода. Размеры массива локальных переменных и стека операндов определяются во время компиляции и предоставляются вместе с кодом для метода, связанного с фреймом. Таким образом, размер структуры данных, frame-а зависит только от реализации виртуальной машины Java, и память для этих структур может быть выделена одновременно при вызове метода.
Frame перестает быть текущим, если его метод вызывает другой метод или если его метод завершается. Когда метод вызывается, новый frame создается и становится текущим, когда управление переходит к новому методу. При возврате метода текущий frame передает результат вызова метода, если таковой имеется, в предыдущий frame. Текущий frame затем отбрасывается, так как предыдущий frame становится текущим. Обратите внимание, что frame, созданный потоком, является локальным для этого потока и на него не может ссылаться ни один другой поток.
Локальные переменные
Каждый frame содержит массив переменных, известных как его локальные переменные. Длина массива локальных переменных frame определяется во время компиляции и предоставляется в двоичном представлении класса или интерфейса вместе с кодом для метода, связанного с frame-ом. Единичная локальная переменная может хранить значение типа: boolean, byte, char, short, int, float, reference, or returnAddress. Пара локальных переменных может хранить значение типов: long или double.
Локальные переменные адресуются путем индексации. Индекс первой локальной переменной равен нулю.
Значение типа long или типа double занимает две последовательные локальные переменные.
JVM использует локальные переменные для передачи параметров при вызове метода. При вызове метода класса все параметры передаются в последовательных локальных переменных, начиная с локальной переменной 0. При вызове метода экземпляра локальная переменная 0 всегда используется для передачи ссылки на объект, для которого вызывается метод экземпляра (this в Java). Любые параметры впоследствии передаются в последовательных локальных переменных, начиная с локальной переменной 1.
Стеки операндов (Operand Stacks)
Стек операнда пуст при создании frame-a, который его содержит. JVM предоставляет инструкции для загрузки констант или значений из локальных переменных или полей в стек операндов. Другие инструкции JVM берут операнды из стека операндов, оперируют с ними и помещают результат обратно в стек операндов. Стек операндов также используется для подготовки параметров для передачи в методы и для получения результатов метода.
Для примера, инструкция iadd суммирует два int-вых значения. От стека операндов требуется, чтобы два int-вых значения были наверху стека. Значения удаляются из стека, операция pop. Суммируются и их сумма помещается в стек операндов.
Динамическое связывание (Dynamic Linking)
Каждый frame содержит ссылку на run-time constant pool для типа текущего метода для поддержки динамического связывания кода метода. Доступ к вызываемым методам и переменным осуществляется через символические ссылки из class файла. Динамическое связывание преобразует эти символьные ссылки на методы в конкретные ссылки на методы, загружая классы по мере необходимости для разрешения пока еще не определенных символов, и преобразует обращения к переменным в соответствующие смещения в структурах хранения, связанных с расположением этих переменных во время выполнения.
Позднее связывание методов и переменных вносит изменения в другие классы, которые метод использует с меньшей вероятностью нарушить этот код.
Нормальное завершение вызова метода
Вызов метода завершается нормально, если этот вызов не вызывает исключение, либо непосредственно из JVM, либо в результате выполнения явного оператора throw. Если вызов текущего метода завершается нормально, то значение может быть возвращено вызывающему методу. Это происходит, когда вызванный метод выполняет одну из инструкций возврата, выбор которых должен соответствовать типу возвращаемого значения (если оно есть).
Текущий frame используется в этом случае для восстановления состояния инициатора, включая его локальные переменные и стек операндов, с соответствующим образом увеличенным программным счетчиком инициатора, чтобы пропустить инструкцию вызова метода. Затем выполнение обычно продолжается в frame вызывающего метода с возвращенным значением (если оно есть), помещаемым в стек операндов этого frame.
Резкое завершение вызова метода
Вызов метода завершается преждевременно, если при выполнении инструкции JVM в методе выдает исключение, и это исключение не обрабатывается в методе. Выполнение команды throw также приводит к явному выбрасыванию исключения, и, если исключение не перехватывается текущим методом, приводит к неожиданному завершению вызова метода. Вызов метода, который завершается внезапно, никогда не возвращает значение своему вызывающему.
Байт-код, назначенный run-time data areas, будет выполнен execution engine. Механизм выполнения считывает байт-код и выполняет его по частям.
Interpreter
Интерпретатор интерпретирует байт-код быстро, но выполняется медленно. Недостаток интерпретатора заключается в том, что, когда один метод вызывается несколько раз, каждый раз требуется новая интерпретация.
JIT Compiler
JIT-компилятор устраняет недостатки интерпретатора. Механизм выполнения будет использовать помощь интерпретатора при преобразовании байт-кода, но когда он находит повторный код, он использует JIT-компилятор, который компилирует весь байт-код и изменяет его на собственный код. Этот нативный код будет использоваться непосредственно для повторных вызовов методов, которые улучшают производительность системы.
Java Virtual Machine Run-Time Data Areas
Summary:
This article contains…
Runtime data areas :
Java virtual machine defines various run-time data areas, Mainly these are part of Stack and Heap.
Basic rule of storing java program in memory is,
Further exploring these, list of run-time data areas in java virtual machine are,
in which some are created on java virtual machine start up and some are per thread which are created on when a thread is created and destroy when thread completes.
Details of runtime data areas :
Program counter register :
We know that JVM can support many thread of execution at once. Each JVM thread has its own PC Register.
At any point of time while executing the code of single method (referred as current method), if it is not a native method, pc register address of JVM instruction currently being executed. For native method, value of pc register is undefined.
Java virtual machine stacks :
Each JVM thread has a private JVM stack, created at the time of thread creation.
JVM stack holds data as a Frame, when a new method will be invoked a frame will be pushed into the jvm stack and popped when method execution completes. No other data, except frame, can be push/popped into JVM stack.
Frames :
Frames are used to store partial results, return value from method, perform dynamic linking and dispatch exceptions.
Lifetime of a frame is equal to method execution time, A frame will be pushed to JVM stack when a method will be invoked and distroyed when method execution completes.
At a point of time, Only one frame at a given time can be in active state per thread, which is frame for function being executed.
Each frame has its own Array of local variables, Operand stack and Reference to run-time constant pool.
Array of local variables :
All local variables of method are stored in this array, single local variable can hold any value of type byte, char, short, int, float, reference, return address and boolean while pair of local variable can hold long and double.
local variables are also used to pass parameters when method is invoked. Where local variable 0 is always used to pass reference of object on which instance method is invoked. (this) Any other parameters will be stored from 1.
Operand stack :
Operand stack holds the operand used by operators to perform operations. Each entry on the operand stack can hold a value of any Java Virtual Machine type.
Java Virtual Machine instructions take operands from the operand stack, operate on them, and push the result back onto the operand stack. The operand stack is also used to prepare parameters to be passed to methods and to receive method results.
For example, iadd instruction will add two integer values, so it will pop top two integer values from operand stack and will push result into operand stack after adding them.
Reference to runtime constant pool (Dynamic linking) :
In class file structure, flow of method that will be invoked and variable to be accessed is stored as symbolic reference. Dynamic linking translates this symbolic reference to concrete method reference and loads the class as required. This reference to runtime constant pool is stored in frame to perform dynamic linking at run-time.
Heap :
Heap is a runtime data area in memory where Objects, Instance variable and Arrays are stored. Heap memory storage may be of fixed size or may be expanded as required by computation, and this memory does not need to be contiguous.
Heap is created at virtual machine startup and Objects which are no more referenced will be deallocated from memory by automatic garbage collector, objects are never explicitly deallocated.
Method area :
Method area is created on virtual machine startup, shared among all java virtual machine threads and it is logically part of heap area. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors.
This can be of fixed size or can be expanded as per requirement of computation.
Run-time constant pool :
Run-time constant pool is per class/interface structure, It is runtime representation of constant_pool table generated at compile time which is stored in class file.
Constant pool contains several literal values or symbolic references that will be resolved at runtime. Runtime constant pool for class/interface is allocated from method area and constructed when class or interface is created by JVM.
See below image of JVM Runtime Data areas.
Exceptional condition in JVM runtime data areas :
There are two exceptions associated with JVM runtime data areas. OutOfMemoryError and StackOverflowError.
OutOfMemoryError is applicable for all of the above listed except PC register. OutOfMemoryError will be thrown if memory expansion of any of the memory area will be attempted but enough memory is not available to allocate.
StackOverflowError is applicable for Native Method Stack and Java Virtual Machine Stack. StackOverflowError will be thrown If the computation in a thread requires a larger stack than is permitted.
Monitor JVM Runtime data areas :
You can check JVM runtime memory allocation using JConsole (Java monitoring and management console)
JConsole window : You can select type of run-time data area from chart dropdown menu.
This was about run-time data areas in JVM which will help you to understand memory allocation and topics like argument passing, polymorphism, threads, exceptions, and garbage collection.
You can always clone the executable code of article posted on Java By Examples from github.com
Repository URL : https://github.com/ksarsecha/java8_in.git
More articles will be available soon on Java and SCJP.
Что такое runtime data areas
Java Virtual Machine
Java (произноситься как «джава») — строго типизированный объектно-ориентированный язык программирования и одноимённая платформа, разработанные компанией Sun Microsystems (в последующем приобретённой компанией Oracle). Разработка ведётся сообществом, организованным через Java Community Process, язык и основные реализующие его технологии распространяются по лицензии GPL. Права на торговую марку принадлежат корпорации Oracle.
Приложения Java обычно транслируются в специальный байт-код, поэтому они могут работать на любой компьютерной архитектуре, для которой существует реализация JVM (виртуальной Java-машины). Дата официального выпуска — 23 мая 1995 года. На текущий момент один из самых популярных языков программирования и де-факто платформа по умолчанию в разработке ПО уровня предприятия.
Основные области применения: приложения для Android-устройств, веб-сервисы и сайты, промежуточное ПО, микропрограммы для встраиваемых систем.
Почему стоить использовать Java?
Какие основные отличия в версиях Java?
Чем различаются JRE, JVM и JDK?
JVM, Java Virtual Machine (Виртуальная машина Java) — основная часть среды времени исполнения Java (JRE). Виртуальная машина Java исполняет байт-код Java, предварительно созданный из исходного текста Java-программы компилятором Java. JVM может также использоваться для выполнения программ, написанных на других языках программирования.
За что отвечает JVM?
JVM работает с 2 типами данных: примитивные типы (primitive types) и ссылочные типы (reference types).
Примитивы
Типы ссылок и значения
Существует три типа ссылочных типов: типы классов, типы массивов и типы интерфейсов. Их значения являются ссылками на динамически создаваемые экземпляры классов, массивы или экземпляры классов, которые реализуют интерфейсы соответственно.
Расскажите про Classloader
Загрузчик классов является частью JRE, которая динамически загружает Java классы в JVM. Обычно классы загружаются только по запросу. Система исполнения в Java не должна знать о файлах и файловых системах благодаря загрузчику классов. Делегирование является важной концепцией, которую выполняет загрузчик. Загрузчик классов отвечает за поиск библиотек, чтение их содержимого и загрузку классов, содержащихся в библиотеках. Эта загрузка обычно выполняется «по требованию», поскольку она не происходит до тех пор, пока программа не вызовет класс. Класс с именем может быть загружен только один раз данным загрузчиком классов.
При запуске JVM, используются три загрузчика классов:
Загрузчик классов выполняет три основных действия в строгом порядке:
Пользовательский загрузчик классов
Загрузчик классов написан на Java. Поэтому возможно создать свой собственный загрузчик классов, не понимая тонких деталей JVM. У каждого загрузчика классов Java есть родительский загрузчик классов, определенный при создании экземпляра нового загрузчика классов или в качестве системного загрузчика классов по умолчанию для виртуальной машины.
Что делает возможным следующее:
Расскажите о Run-Time Data Area
Run-Time Data Areas. JVM выделяет множество областей данных во время выполнения, которые используются во время выполнения программы. Некоторые участки данных созданы JVM во время старта и уничтожаются во время её выключения. Другие создаются для каждого потока и уничтожаются, когда поток уничтожается.
The pc Register (PCR)
Виртуальная машина Java может поддерживать много потоков исполнения одновременно. Каждый поток виртуальной машины Java имеет свой собственный регистр PC (programm counter). В любой момент каждый поток виртуальной машины Java выполняет код одного метода, а именно текущий метод для этого потока. Если этот метод не является native, регистр pc содержит адрес инструкции виртуальной машины Java, выполняемой в настоящее время.
Коротко говоря: для одного потока существует один PCR, который создается при запуске потока. PCR хранит адрес выполняемой сейчас инструкции JVM.
Java Virtual Machine Stacks
Каждый поток в JVM имеет собственный стек, созданный одновременно с потоком. Стек в JVM хранит frames. Стеки в JVM могут иметь фиксированный размер или динамически расширяться и сжиматься в соответствии с требованиями вычислений.
Heap
Method Area
JVM имеет область методов, которая является общей для всех потоков. Она хранит структуры для каждого класса, такие как пул констант, данные полей и методов, а также код для методов и конструкторов, включая специальные методы, используемые при инициализации классов и экземпляров, и инициализации интерфейса. Хотя область метода является логически частью кучи, простые реализации могут не обрабатываться сборщиком мусора. Область метода может иметь фиксированный размер или может быть расширена в соответствии с требованиями вычислений и может быть сокращена, если большая область метода становится ненужной.
Run-Time Constant Pool
A run-time constant pool существует для каждого класса или интерфейса в рантайме и представлено constant_pool таблицей в *.class файле. Он содержит несколько видов констант: от числовых литералов, известных во время компиляции, до ссылок на методы и поля, которые должны быть разрешены во время выполнения. Сам run-time constant pool выполняет функцию, аналогичную функции таблицы символов для обычного языка программирования, хотя он содержит более широкий диапазон данных, чем типичная таблица символов. Каждый run-time constant pool отделён от JVM’s method area. JVM создаёт run-time constant pool вместе с созданием class или interface.
Native Method Stacks
Реализация виртуальной машины Java может использовать обычные стеки, обычно называемые «стеки Си», для поддержки native methods (методов, написанных на языке, отличном от языка программирования Java).
Как рассчитать объем, который занимают объекты в памяти?
Заголовок объекта занимает 12 байт:
Название | Размер, байт | Описание |
---|---|---|
Class pointer | 4 | Ссылка на описание класса |
Mark word | 8 | Набор флагов, описывающих состояние объекта |
Расскажите о Frames
Frame используется для хранения данных и частичных результатов, а также для выполнения динамического связывания, возврата значений для методов и отправки исключений. Новый frame создается каждый раз, когда вызывается метод. Frame уничтожается, когда завершается вызов метода, является ли это завершение нормальным или резким (он генерирует неперехваченное исключение). Frames выделяются из стека потока, создающего frame. Каждый frame имеет свой собственный массив локальных переменных, свой собственный стек операндов и ссылку на пул констант во время выполнения класса текущего метода. Размеры массива локальных переменных и стека операндов определяются во время компиляции и предоставляются вместе с кодом для метода, связанного с фреймом. Таким образом, размер структуры данных frame-а зависит только от реализации виртуальной машины Java, и память для этих структур может быть выделена одновременно при вызове метода.
Frame перестает быть текущим, если его метод вызывает другой метод или если его метод завершается. Когда метод вызывается, новый frame создается и становится текущим, когда управление переходит к новому методу. При возврате метода текущий frame передает результат вызова метода, если таковой имеется, в предыдущий frame. Текущий frame затем отбрасывается, так как предыдущий frame становится текущим. Обратите внимание, что frame, созданный потоком, является локальным для этого потока и на него не может ссылаться ни один другой поток.
Локальные переменные
Каждый frame содержит массив переменных, известных как его локальные переменные. Длина массива локальных переменных frame определяется во время компиляции и предоставляется в двоичном представлении класса или интерфейса вместе с кодом для метода, связанного с frame-ом. Единичная локальная переменная может хранить значение типа: boolean, byte, char, short, int, float, reference, or returnAddress. Пара локальных переменных может хранить значение типов: long или double.
Локальные переменные адресуются путем индексации. Индекс первой локальной переменной равен нулю.
Значение типа long или типа double занимает две последовательные локальные переменные.
JVM использует локальные переменные для передачи параметров при вызове метода. При вызове метода класса все параметры передаются в последовательных локальных переменных, начиная с локальной переменной 0. При вызове метода экземпляра локальная переменная 0 всегда используется для передачи ссылки на объект, для которого вызывается метод экземпляра (this в Java). Любые параметры впоследствии передаются в последовательных локальных переменных, начиная с локальной переменной 1.
Стеки операндов (Operand Stacks)
Стек операнда пуст при создании frame-a, который его содержит. JVM предоставляет инструкции для загрузки констант или значений из локальных переменных или полей в стек операндов. Другие инструкции JVM берут операнды из стека операндов, оперируют с ними и помещают результат обратно в стек операндов. Стек операндов также используется для подготовки параметров для передачи в методы и для получения результатов метода.
Для примера, инструкция iadd суммирует два int значения. От стека операндов требуется, чтобы два int значения были наверху стека. Значения удаляются из стека, операция pop. Суммируются и их сумма помещается в стек операндов.
Динамическое связывание (Dynamic Linking)
Каждый frame содержит ссылку на run-time constant pool для типа текущего метода для поддержки динамического связывания кода метода. Доступ к вызываемым методам и переменным осуществляется через символические ссылки из class файла. Динамическое связывание преобразует эти символьные ссылки на методы в конкретные ссылки на методы, загружая классы по мере необходимости для разрешения пока еще не определенных символов, и преобразует обращения к переменным в соответствующие смещения в структурах хранения, связанных с расположением этих переменных во время выполнения.
Позднее связывание методов и переменных вносит изменения в другие классы, которые метод использует с меньшей вероятностью нарушить этот код.
Нормальное завершение вызова метода
Вызов метода завершается нормально, если этот вызов не вызывает исключение, либо непосредственно из JVM, либо в результате выполнения явного оператора throw. Если вызов текущего метода завершается нормально, то значение может быть возвращено вызывающему методу. Это происходит, когда вызванный метод выполняет одну из инструкций возврата, выбор которых должен соответствовать типу возвращаемого значения (если оно есть).
Текущий frame используется в этом случае для восстановления состояния инициатора, включая его локальные переменные и стек операндов, с соответствующим образом увеличенным программным счетчиком инициатора, чтобы пропустить инструкцию вызова метода. Затем выполнение обычно продолжается в frame вызывающего метода с возвращенным значением (если оно есть), помещаемым в стек операндов этого frame.
Резкое завершение вызова метода
Вызов метода завершается преждевременно, если при выполнении инструкции JVM в методе выдает исключение, и это исключение не обрабатывается в методе. Выполнение команды athrow также приводит к явному выбрасыванию исключения, и если исключение не перехватывается текущим методом, приводит к неожиданному завершению вызова метода. Вызов метода, который завершается внезапно, никогда не возвращает значение своему вызывающему.
Что такое Execution Engine?
Байт-код, назначенный run-time data areas, будет выполнен execution engine. Механизм выполнения считывает байт-код и выполняет его по частям.
Interpreter
Интерпретатор интерпретирует байт-код быстро, но выполняется медленно. Недостаток интерпретатора заключается в том, что когда один метод вызывается несколько раз, каждый раз требуется новая интерпретация.
JIT Compiler
JIT-компилятор устраняет недостатки интерпретатора. Механизм выполнения будет использовать помощь интерпретатора при преобразовании байт-кода, но когда он находит повторный код, он использует JIT-компилятор, который компилирует весь байт-код и изменяет его на собственный код. Этот нативный код будет использоваться непосредственно для повторных вызовов методов, которые улучшают производительность системы.
Garbage Collector Garbage Collector («сборщик мусора») функционирует в фоновом режиме во время работы твоей программы, собирает ставшие ненужными объекты, которые в дальнейшем будут удалены. Таким образом, он освобождает память для создания новых объектов в будущем. На самом деле сборщик мусора не один, а несколько.
Для чего нужен сборщик мусора?
Сборщик мусора (Garbage Collector) должен делать всего две вещи:
Существует два подхода к обнаружению мусора:
Существует 4 типа корневых точки:
Самое простое java приложение будет иметь корневые точки:
Для очистки памяти от мусора существуют два основных метода:
При copying collectors подходе память делится на две части «from-space» и «to-space», при этом сам принцип работы такой:
Главный плюс такого подхода в том, что объекты плотно забивают память. Минусы подхода:
Алгоритм работы mark-and-sweep можно описать так:
Минусы этого способа:
Сборщики мусора HotSpot VM используют комбинированный подход Generational Garbage Collection, который позволяет использовать разные алгоритмы для разных этапов сборки мусора. Этот подход опирается на том, что:
Как работает сборщик мусора?
Виртуальная машина Java, применяя механизм сборки мусора, гарантирует, что любой объект, обладающий ссылками, остается в памяти — все объекты, которые недостижимы из исполняемого кода, ввиду отсутствия ссылок на них, удаляются с высвобождением отведенной для них памяти. Точнее говоря, объект не попадает в сферу действия процесса сборки мусора, если он достижим посредством цепочки ссылок, начиная с корневой (GC Root) ссылки, т.е. ссылки, непосредственно существующей в выполняемом коде.
Память освобождается сборщиком мусора по его собственному «усмотрению». Программа может успешно завершить работу, не исчерпав ресурсов свободной памяти или даже не приблизившись к этой черте и поэтому ей так и не потребуются «услуги» сборщика мусора.
Мусор собирается системой автоматически, без вмешательства пользователя или программиста, но это не значит, что этот процесс не требует внимания вовсе. Необходимость создания и удаления большого количества объектов существенным образом сказывается на производительности приложений и если быстродействие программы является важным фактором, следует тщательно обдумывать решения, связанные с созданием объектов, — это, в свою очередь, уменьшит и объем мусора, подлежащего утилизации.
Какие разновидности сборщиков мусора реализованы в виртуальной машине HotSpot?
Java HotSpot VM предоставляет разработчикам на выбор четыре различных сборщика мусора:
Опишите алгоритм работы какого-нибудь сборщика мусора реализованного в виртуальной машине HotSpot.
Serial Garbage Collector (Последовательный сборщик мусора) был одним из первых сборщиков мусора в HotSpot VM. Во время работы этого сборщика приложения приостанавливается и продолжает работать только после прекращение сборки мусора.
Память приложения делится на три пространства:
Если в процессе копирования живых объектов To space переполняется, то оставшиеся живые объекты из Eden и From space, которым не хватило места в To space, будут перемещены в Old generation, независимо от того, сколько сборок мусора они пережили.
Поскольку при использовании этого алгоритма сборщик мусора просто копирует все живые объекты из одной области памяти в другую, то такой сборщик мусора называется copying (копирующий). Очевидно, что для работы копирующего сборщика мусора у приложения всегда должна быть свободная область памяти, в которую будут копироваться живые объекты, и такой алгоритм может применяться для областей памяти сравнительно небольших по отношению к общему размеру памяти приложения. Young generation как раз удовлетворяет этому условию (по умолчанию на машинах клиентского типа эта область занимает около 10% кучи (значение может варьироваться в зависимости от платформы)).
Однако для сборки мусора в Old generation, занимающем большую часть всей памяти, используется другой алгоритм.
В Old generation сборка мусора происходит с использованием алгоритма mark-sweep-compact, который состоит из трёх фаз. В фазе Mark (пометка) сборщик мусора помечает все живые объекты, затем, в фазе Sweep (очистка) все не помеченные объекты удаляются, а в фазе Compact (уплотнение) все живые объекты перемещаются в начало Old generation, в результате чего свободная память после очистки представляет собой непрерывную область. Фаза уплотнения выполняется для того, чтобы избежать фрагментации и упростить процесс выделения памяти в Old generation.
Когда свободная память представляет собой непрерывную область, то для выделения памяти под создаваемый объект можно использовать очень быстрый (около десятка машинных инструкций) алгоритм bump-the-pointer: адрес начала свободной памяти хранится в специальном указателе, и когда поступает запрос на создание нового объекта, код проверяет, что для нового объекта достаточно места, и, если это так, то просто увеличивает указатель на размер объекта.
Последовательный сборщик мусора отлично подходит для большинства приложений, использующих до 200 мегабайт кучи, работающих на машинах клиентского типа и не предъявляющих жёстких требований к величине пауз, затрачиваемых на сборку мусора. В то же время модель «stop-the-world» может вызвать длительные паузы в работе приложения при использовании больших объёмов памяти. Кроме того, последовательный алгоритм работы не позволяет оптимально использовать вычислительные ресурсы компьютера и последовательный сборщик мусора может стать узким местом при работе приложения на многопроцессорных машинах.
Что такое Safepoints (применительно к HotSpot JVM)?
В HotSpot JVM механизм паузы «stop-the-world» называется safepoint. Во время safepoint все потоки, исполняющие java-код приостанавливаются. Потоки, исполняющие нативный код, могут продолжать работать пока, не будут прерваны JVM (попытка доступа к объектам Java через JNI, вызов метода Java или возврат из нативного кода в Java приостановит поток до конца safepoint). Остановка всех потоков необходима, чтобы убедиться, что safepoint-инициатор имеет эксклюзивный доступ к структурам данных JVM и может делать всё что угодно, например перемещение объектов в куче или замена кода метода, который в настоящее время выполняется (перемещение в стеке).
Как работают safepoints? Протокол Safepoint в HotSpot JVM является общим. Каждый поток приложения проверяет статус safepoint и паркуется в безопасном состоянии в этой точке. Для скомпилированного кода JIT вставляет в код проверки safepoint в определенных точках (обычно после возврата вызовов или при обратном переходе цикла). Для интерпретируемого кода JVM имеет две таблицы диспетчеризации байт-кода, и если требуется safepoint, JVM переключает таблицы, чтобы включить его проверку.
Сама проверка статуса Safepoint реализована очень нетривиально. Обычная проверка переменных памяти потребует дорогостоящих барьеров памяти. Хотя проверка safepoints реализована через барьер. Затем требуется безопасная точка, JVM отключает отображение страницы с этим адресом, вызывая сбой страницы в потоке приложения (который обрабатывается обработчиком JVM). Таким образом, HotSpot поддерживает свой JITed-код, совместимый с конвейером процессора, но при этом обеспечивает правильную семантику памяти (unmap страницы создает барьер памяти для ядер обработки).
Когда safepoint используется?
Что такое HeapDump и TreadDump?
Что такое профилирование?
Профилирование — сбор характеристик работы программы, таких как время выполнения отдельных фрагментов (обычно подпрограмм), число верно предсказанных условных переходов, число кэш-промахов и т. д. Инструмент, используемый для анализа работы, называют профилировщиком или профайлером (англ. profiler). Обычно выполняется совместно с оптимизацией программы.
Как обнаружить причину утечки памяти (memory leak)?
Что может быть причиной:
Рекомендации по диагностированию:
Какие существуют рекомендации к стилю кода на Java?
Рекомендации к стилю кода отражены в документе Java Code Conventions.
Какие языки (кроме Java) могут быть использованы в разработке ПО, исполняемого в среде JVM?
Компилируемые в байт-код Java: Scala — объектно-ориентированный и функциональный язык; Kotlin — объектно-ориентированный язык, используется, в том числе для разработки Android-приложений; Clojure — функциональный язык, диалект Lisp; Ceylon — объектно-ориентированный язык со строгой статической типизацией.