This is my original deep-dive note, converted to Markdown word-for-word.
Nothing removed. Source of the stack-vs-heap thread-safety insight.
Contents
-
Virtual Machine
-
JVM
-
JRE
-
Why JVM
-
Function of JVM
-
Features of JVM
-
Stack-based virtual machine
-
Symbolic reference
-
Garbage collection
-
Guarantees platform independence by clearly defining the primitive data
type -
Network byte order
-
java command
-
Components of JVM
-
Class loader
-
Execution Engine
-
Data / Memory Areas
-
Classloader
-
Quick
-
Detailed
-
Features of Java class loader
-
Hierarchical Structure
-
Delegation mode
-
Visibility limit
-
Unload is not allowed
-
Components/ Phases of Classloader
-
Loading
-
Bootstrap class loader
-
Extension class loader
-
Application / System class loader
-
User-defined class loader
-
Linking
-
Verifying
-
Preparing:
-
Resolving:
-
Initialization
-
Runtime Data Area
-
Method / Class Area
-
Metaspace
-
Method Area in some detail
-
Quick
-
Detailed
-
The Constant Pool
-
Field Information
-
Method Information
-
Class Variables
-
A Reference to Class ClassLoader
-
A Reference to Class Class
-
Heap Area
-
OutOfMemoryError in Java Heap
-
PC (Program Counter) Registers
-
Register Area
-
JVM (Java Thread) Stacks
-
Frames
-
Operand Stack
-
Local variable array
-
Run-time constant pool reference
-
Native Method stacks
-
Execution Engine
-
Interpreter
-
JIT (Just-In-Time) compiler
-
Intermediate Code generator
-
Code Optimizer
-
Target Code Generator
-
(Hotspot) Profiler
-
Garbage Collector
-
Java Native Interface (JNI)
-
Native Method Libraries
-
Performance
-
Summary
-
Questions
-
Constant Pool
-
Commands
-
Check
Virtual Machine
A virtual machine (VM)* is a software implementation of a machine (i.e.
a computer) that executes programs like a physical machine.*
JVM
The Java Virtual (or abstract) Machine (JVM) that analyzes and executes
Java byte code instructions.
JRE
The JRE is composed of the Java API and the JVM. It is an implementation
of the JVM specification. The role of the JVM is to read the Java
application through the Class Loader and execute it along with the Java
API.
Why JVM
-
For implementation of WORA (Write Once
Run Anywhere) principle, Java was designed to run based on a
virtual machine separated from a physical machine. -
Once source code (.java file) is compiled on one platform (bytecode
is formed), that bytecode can be executed (interpreted) on any other
platform running a JVM. -
The compiler compiles the Java file into a Java .class file, then
that .class file is input into the JVM, which Loads and executes the
class file. -
Therefore, the JVM runs on all kinds of hardware to execute
the Java Bytecode without changing the Java execution code. -
The implementations of JVM vary depending on the operating system it
is meant for -
Sun Microsystems developed Java. However, any vendor can develop and
provide a JVM by following the Java Virtual Machine Specification.
For this reason, there are various JVMs, including Oracle Hotspot JVM and IBM JVM.
Function of JVM
Java Virtual Machine (JVM), analyzes the bytecode, interprets the
code, and executes it.
-
Loading, verifying, and executing the byte code (application, which is
a .class file)
-
Providing a runtime environment for execution of byte code
-
Memory management and garbage collection
Features of JVM
The features of JVM are as follows:
Stack-based virtual machine
The most popular computer architectures such as Intel x86 Architecture
and ARM Architecture run based on a register. However, JVM runs based
on a stack.
Symbolic reference
All types (class and interface) except for primitive data types are
referred to through symbolic reference, instead of through explicit
memory address-based reference.
Garbage collection
A class instance is explicitly created by the user code and
automatically destroyed by garbage collection.
Guarantees platform independence by clearly defining the primitive data type
A traditional language such as C/C++ has different int type size
according to the platform. The JVM clearly defines the primitive data
type to maintain its compatibility and guarantee platform
independence.
Network byte order
The Java class file uses the network byte order. To maintain platform
independence between the little endian used by Intel x86 Architecture
and the big endian used by the RISC Series Architecture, a fixed byte
order must be kept. Therefore, JVM uses the network byte order, which
is used for network transfer. The network byte order is the big
endian.
java command
Creates a JVM instance which load and executes class file using Class
loader and Execution Engine respectively

Components of JVM
The JVM is divided into three main subsystems
-
Class Loader
-
Runtime Data (Memory) Areas
-
Execution Engine

Class loader
This is responsible for loading the class files or byte code files. It
verifies class files using a bytecode verifier. A class file will only
be loaded if it is valid. The class loader is responsible for loading classes and interfaces residing in the byte code. It
consists of three distinct phases whose function are
-
Load - Loading byte code
-
Link - Linking (verification, memory allocation for byte code, and
resolution or transformation of symbolic references to direct
references) -
Initialize - Initialization of variables to their default values
Execution Engine
-
It executes the byte code
-
Talks to the host operation system in order to execute the
instructions finally against the machine instruction set -
Makes use of native method calls which translate bytecode into machine
codes value and carry out the operations
Data / Memory Areas
- Used to load class bytecode to a memory area
Classloader
Quick

Detailed
Java’s dynamic class
loading functionality
is handled by the class loader subsystem. It loads, links. and
initializes the class file when it refers to a class for the first time at runtime, not compile time**. **
Features of Java class loader
Hierarchical Structure
Class loaders in Java are organized into a hierarchy with a parent-child relationship. The Bootstrap
Class Loader is the parent of all class loaders.
Delegation mode
Based on the hierarchical structure, load is delegated between class
loaders. When a class is loaded, the parent class
loader is checked to determine whether or not the class is in the
parent class loader. If the upper-class loader has the class, the class
is used. If not, the class loader requested for loading loads the class.
Visibility limit
A child class loader can find the class in the parent class loader;
however, a parent class loader cannot find the class
in the child class loader. (reverse of inheritance)
Unload is not allowed
A class loader can load a class but cannot unload
it. Instead of unloading, the current class loader can be
deleted, and a new class loader can be created.
Each class loader has its namespace that stores the
loaded classes. When a class loader loads a class, it searches
the class based on FQCN (Fully Qualified Class
Name) stored in the namespace to check whether or not the class has been
already loaded. Even if the class has an identical
FQCN but a different namespace, it is regarded as a different
class. A different namespace means that the class has been loaded by
another class loader
Components/ Phases of Classloader
Loading
-
A class is obtained from a file and loaded to the JVM memory
-
The Class Loaders will follow Delegation Hierarchy
Algorithm** **while loading the class files.- When a class loader is requested for class load, it checks whether
or not the class exists in the class loader cache, the parent
class loader, and itself, in the order listed.
- When a class loader is requested for class load, it checks whether
-
Boot Strap class Loader, Extension class Loader, and Application class
Loader are the three-class loader which will help in achieving it
Bootstrap class loader
-
This is created when running the JVM
-
Responsible for loading classes from the bootstrap classpath, nothing
but rt.jar -
It loads Java APIs, including object classes
-
Highest priority will be given to this loader
-
Unlike other class loaders, it is implemented in native code instead of Java.
Extension class loader
-
Responsible for loading classes which are
inside ext folder (jre\lib) -
It loads the extension classes excluding the basic Java APIs.
-
It also loads various security extension
functions.
Application / System class loader
-
If the bootstrap class loader and the extension class loader load the
JVM components, the system class loader loads the application classes
using Application Level Classpath -
It loads the class in the Environment Variable $CLASSPATH specified by the user.
User-defined class loader
- This is a class loader that an application user directly creates on
the code.
Linking
Verifying
-
Check whether or not the read class is configured as described in the
Java Language Specification and JVM specifications. -
This is the most complicated test process of the class load processes
and takes the longest time. -
Bytecode verifier will verify whether the generated bytecode is proper
or not if verification fails we will get the verification error.
Preparing:
-
Prepare a data structure that assigns the memory required by classes
and indicates the fields, methods, and interfaces defined in the
class. -
All static variables memory will be
allocated and assigned with default values.
Resolving:
- Change all symbolic memory references in the
constant pool of the class to direct / original references from Method Area**.**
Initialization
-
Initialize the class variables to proper values.
-
Execute the static initializers and initialize the static fields to
the configured values.-
All static
variables** **will
be assigned with the original values and -
the static
block will
be executed.
-
Runtime Data Area
Runtime Data Areas are the memory areas assigned when the JVM program
runs on the OS. The runtime data areas can be divided into 5 major
areas.
-
Method / Class Area, Metaspace( Java8)
-
Heap Area
-
PC Registers
-
Java Stacks
-
Native Method Stacks
Of the five, one PC Register, JVM Stack and Native Method Stack are
created for one thread.
Heap, Method Area, and Runtime Constant Pool are
shared by all threads.
Link - Oracle JVM
Structure
Method / Class Area
-
Created on JVM Startup
-
All the class level data (metadata corresponding to class) are
stored here, including-
static variables
-
bytecode
-
class level Runtime Constant Pool
-
field
-
method data
-
the code for methods and constructors
- including the special methods used in
class, instance, and interface initialization.
- including the special methods used in
-
-
There is only one method area per JVM hence it is a shared resource
-
Java reflection API for the class class enquires data in the method
area -
It is the memory allocated to the JVM i.e the system’s (physical
machine) physical memory, if you are talking about JVM for computer -
Although it is logically a part of the heap but it can or cannot be
garbage collected- whereas garbage collection in heap is mandatory.
-
Also known as PermGen (Permanent Generation) Space
-
By default, 64 MB is allocated
-
It can be tuned if more memory is needed using
-
-XX:MaxPermSize, Can be set to certain MB or GB, as needed
-
java.lang.OutOfMemoryError: PermGen space
https://stackoverflow.com/questions/88235/dealing-with-java-lang-outofmemoryerror-permgen-space-error -
java.lang.OutOfMemoryError: Metaspace
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks002.html
-
-
Metaspace
Java 8 has gotten rid of the Method area / PermGen and now uses
Metaspace for similar functionality.
-
Moved the Method area into a separate memory in the native operating
system, known as Metaspace -
Metaspace is a part of native memory
-
By default, there is no limit to the size of metaspace in Java 8
-
It can just grow as long as needed and can occupy full memory
-
However, if it grows more than the available
physical memory, then the operating system will use virtual
memory. This will have an adverse effect on application
performance, as swapping the data from virtual memory to
physical memory and vice versa is a costly operation.- Will throw out of memory operation
-
-
It can be tuned to limit its size
- -XX:MaxMetaspaceSize=512m
Difference between PermGen and Metaspace
Method Area in some detail
Quick
[Ref]
The method area is responsible for storing class information. The
Class-Loader will load the bytecode of a class and will pass it to the
JVM. The JVM will generate an internal class representation of the
bytecode and store it in the method area. The internal representation of
a class will have the following data areas:
-
Runtime Constant Pool
- Numeric constants of the class of types int, long, float or double,
String-constants and symbolic references to all methods, attributes
and types of this class.
- Numeric constants of the class of types int, long, float or double,
-
Method Code
- The implementation (code) of all methods of this class including
constructors etc.
- The implementation (code) of all methods of this class including
-
Attributes
- A list of all named attributes of this class.
-
FieldsValues
- of all fields of this class as references to the Runtime Constant
Pool.
- of all fields of this class as references to the Runtime Constant
Detailed
[Ref]
-
Inside a Java virtual machine instance, information about loaded
types is stored in a logical area of memory called the method area.
When the Java virtual machine loads a type, it uses a class loader
to locate the appropriate class file. The class loader reads in the
class file—a linear stream of binary data—and passes it to the
virtual machine. The virtual machine extracts information about the
type from the binary data and stores the information in the method
area. Memory for class (static) variables declared in the class is
also taken from the method area. The virtual machine will search
through and use the type information stored in the method area as it
executes the application it is hosting. All threads share the same
method area, so access to the method area’s data structures must be
designed to be thread-safe. -
The size of the method area need not be fixed. Also, the memory of
the method area need not be contiguous. -
The method area can also be garbage collected. Because Java programs
can be dynamically extended via user-defined class loaders, classes
can become “unreferenced” by the application. If a class becomes
unreferenced, a Java virtual machine can unload the class (garbage
collects it) to keep the memory occupied by the method area at a
minimum. -
In addition to the basic type information listed previously, the
virtual machine must also store for each loaded type:-
The constant pool for the type
-
Field information
-
Method information
-
All class (static) variables declared in the type, except
constants -
A reference to class ClassLoader
-
A reference to class Class
-
The Constant Pool
[Ref]
The constant pool is a pool of constants. In other words, it contains a
list of all the constants contained in a class. Note that each class has
its own constant pool in memory. The constants are literals that don’t
change over time.
[Ref 2] An
area that corresponds to the constant_pool table in the class file
format. This area is included in the method area; however, it plays the
most core role in JVM operation. Therefore, the JVM specification
separately describes its importance. As well as the constant of each
class and interface, it contains all references for methods and fields.
In short, when a method or field is referred to, the JVM searches the
actual address of the method or field on the memory by using the runtime
constant pool.
For each type it loads, a Java virtual machine must store a constant
pool. A constant pool is an ordered set of constants
used by the type, including literals (string, integer, and
floating-point constants) and symbolic references to types, fields, and
methods. Entries in the constant pool are referenced by index,
much like the elements of an array. Because it holds
symbolic references to all types, fields, and methods used by a type,
the constant pool plays a central role in the dynamic linking of Java
programs. The constant pool is described in more detail later in
this chapter and in Chapter 6, “The Java Class File.”
Field Information
For each field declared in the type, the following information must be
stored in the method area. In addition to the information for each
field, the order in which the fields are declared by the class or
interface must also be recorded. Here’s the list for fields:
-
The field’s name
-
The field’s type
-
The field’s modifiers (some subset
of public, private, protected, static, final, volatile, transient)
Method Information
For each method declared in the type, the following information must be
stored in the method area. As with fields, the order in which the
methods are declared by the class or interface must be recorded as well
as the data. Here’s the list:
-
The method’s name
-
The method’s return type (or void)
-
The number and types (in order) of the method’s parameters
-
The method’s modifiers (some subset
of public, private, protected, static, final, synchronized, native, abstract)
In addition to the items listed previously, the following information
must also be stored with each method that is not abstract or native:
-
The method’s bytecodes
-
The sizes of the operand stack and local variables sections of the
method’s stack frame (these are described in a later section of this
chapter) -
An exception table (this is described in Chapter 17, “Exceptions”)
Class Variables
Class variables are shared among all instances of a class and can be
accessed even in the absence of any instance. These variables are
associated with the class—not with instances of the class—so they are
logically part of the class data in the method area. Before a Java
virtual machine uses a class, it must allocate memory from the method
area for each non-final class variable declared in the class.
Constants (class variables declared final) are not treated in the same
way as non-final class variables. Every type that uses a final class
variable gets a copy of the constant value in its own constant pool. As
part of the constant pool, final class variables are stored in the
method area—just like non-final class variables. But whereas non-final
class variables are stored as part of the data for the type
that declares them, final class variables are stored as part of the
data for any type that uses them. This special treatment of constants
is explained in more detail in Chapter 6, “The Java Class File.”
A Reference to Class ClassLoader
For each type it loads, a Java virtual machine must keep track of
whether or not the type was loaded via the bootstrap class loader or a
user-defined class loader. For those types loaded via a user-defined
class loader, the virtual machine must store a reference to the
user-defined class loader that loaded the type. This information is
stored as part of the type’s data in the method area.
The virtual machine uses this information during dynamic linking. When
one type refers to another type, the virtual machine requests the
referenced type from the same class loader that loaded the referencing
type. This process of dynamic linking is also central to the way the
virtual machine forms separate name spaces. To be able to properly
perform dynamic linking and maintain multiple name spaces, the virtual
machine needs to know what class loader loaded each type in its method
area. The details of dynamic linking and name spaces are given in
Chapter 8, “The Linking Model.”
A Reference to Class Class
An instance of class java.lang.Class is created by the Java virtual
machine for every type it loads. The virtual machine must in some way
associate a reference to the Class instance for a type with the type’s
data in the method area.
Your Java programs can obtain and use references to Class objects. One
static method in class Class, allows you to get a reference to
the Classinstance for any loaded class:
Heap Area
-
The heap is the place where all objects data (their corresponding
instance variables) are stored-
Every time an object is instantiated (using new operator), that
object is created in the heap -
Arrays will be stored here only
-
-
The heap area also contains the Garbage Collected Heap
-
The garbage collected heap is an area of the memory within the
context of the JVM where objects are stored -
It de-allocates the memory occupied by these objects as and when
they are no longer needed or referenced in the code. -
The GC works on the basis of two principles - reference counting
and mark and sweep -
The local object references reside in the
stack whereas the actual objects are stored in the heap.
The GC works in the background and releases memory when objects
are no longer in use.
-
-
Only one Heap Area per JVM is available.
- Since the Method and Heap areas share memory
for multiple threads, the data stored is not thread safe.
- Since the Method and Heap areas share memory
-
Most of the time needs to be tuned based on the application
requirements( use m and g to specify MB or GB)-
-Xms, Minimum (Initial Size), Default - one
fourth of the physical memory -
-Xmx, Maximum Size, Default – min {1/4th of
the physical memory, 1GB}
-
-
Heap sizes
Initial heap size of 1/64 of physical memory up to 1Gbyte
Maximum heap size of 1/4 of physical memory up to 1Gbyte
https://www.mkyong.com/java/find-out-your-java-heap-memory-size/
http://javarevisited.blogspot.sg/2012/01/tomcat-javalangoutofmemoryerror-permgen.html
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gc-ergonomics.html
https://stackoverflow.com/questions/28272923/default-xmxsize-in-java-8/28273076
OutOfMemoryError in Java Heap
-
When JVM starts JVM heap space is equal to the initial size of Heap
specified by -Xms parameter -
As application progress more objects get created and heap space is
expanded to accommodate new objects. JVM also run garbage collector
periodically to reclaim memory back from dead objects -
The JVM expands Heap in Java somewhere near to Maximum Heap Size
specified by -Xmx -
If there is no more memory left for creating new object in java heap
, JVM throws java.lang.OutOfMemoryError
and your application dies. -
Before throwing OutOfMemoryError No Space in Java
Heap-
JVM tries to run garbage collector to free any available space
but even after that not much space available on Heap in Java it
results into OutOfMemoryError. -
To resolve this error you need to understand your application
object profile i.e. what kind of object you are creating, which
objects are taking how much memory etc. you can use profiler or heap
analyzer to troubleshoot OutOfMemoryError in Java.
-
-
The “java.lang.OutOfMemoryError: Java heap
space” error messages denotes that Java heap does not have
sufficient space and cannot be expanded further
while “java.lang.OutOfMemoryError: PermGen
space” error message comes when the permanent generation of
Java Heap is full, the application will fail to load a
class or
to allocate an interned string.Read
more: http://javarevisited.blogspot.com/2011/05/java-heap-space-memory-size-jvm.html#ixzz59vxvIGAI
PC (Program Counter) Registers
Each thread has its own PC Registers, to hold the address of current
executing instruction. Once the instruction is executed the PC register
will be updated with the next instructions
-
The program counter registers contain the address of the
instructions currently being executed and the address of next
instruction as well -
If the method currently being executed by the thread is native, the
value of the Java Virtual Machine’s pc register is undefined. The
Java Virtual Machine’s pc register is wide enough to hold
a returnAddress or a native pointer on the specific platform.
[Ref]
Register Area
This contains the registers used by the JVM. The JVM contains four
registers: pc, optop, frame, and vars. Here is what these registers are
used for
[Ref]
-
pc: This is the program counter or the register that points to the
address of the currently executing instruction. -
optop: This is the register that contains the address of the top of
the operand stack. -
frame: This register points to the execution environment of the
currently executing method. -
vars: This register points to the first local variable in the
currently executing method.
JVM (Java Thread) Stacks
Stack memory is responsible for holding references to heap objects and
for storing value types (also known in Java as primitive types), which
hold the value itself rather than a reference to an object from the
heap. In addition, variables on the stack have a certain visibility,
also called scope. Only objects from the active scope are used.
For example, assuming that we do not have any global scope variables
(fields), and only local variables, if the compiler executes a method’s
body, it can access only objects from the stack that are within the
method’s body. It cannot access other local variables, as those are out
of scope. Once the method completes and returns, the top of the stack
pops out, and the active scope changes.
In The Java Virtual Machine Specification, First Edition, the Java
Virtual Machine stack was known as the Java stack.
*Java Virtual Machine Stack *Each thread gets its own stack on which so
called Frames are pushed for each method the thread currently
executed. This means that there can be many frames on the stack for
nested method calls – but there is only one frame active at the same
time for one thread. The frame contains the local variables of the
method, a reference to the Runtime Constant Pool of the method’s class
and an operand stack for the execution of JVM operations. (The JVM is a
stack machine!)
[Ref]

-
Creation
-
Each JVM thread has a private JVM Stack, created at the same
time as the thread. -
Its memory need not be contiguous
-
-
Memory
-
Similar to heap, the memory for a Java Virtual Machine stack
does not need to be contiguous. -
The specification permits Java Virtual Machine stacks either to
be of a fixed size or to dynamically expand and contract as
required by the computation. -
If the Java Virtual Machine stacks are of a fixed size, the size
of each Java Virtual Machine stack may be chosen independently
when that stack is created. -
User can control
-
The initial size of the stack for a fixed size
-
Min and max limit for dynamically expanding or contracting
Java Virtual Machine stacks
-
-
Exception
-
If the computation in a thread requires a larger Java
Virtual Machine stack than is permitted, the Java Virtual
Machine throws
a StackOverflowError -
If Java Virtual Machine stacks can be dynamically expanded,
and expansion is attempted but insufficient memory can be
made available to effect the expansion, or if insufficient
memory can be made available to create the initial Java
Virtual Machine stack for a new thread, the Java Virtual
Machine throws
an OutOfMemoryError.
-
-
-
Operation
-
Never manipulated directly except to push and pop frames
-
Hence, frames may be heap allocated.
-
-
Storage
- A Java Virtual Machine stack stores Stack frames
Frames
A stack frame is a data structure that contains multiple data that
represent the state of the thread in the current method (the method
being called). It is created whenever a method is executed in the JVM,
and then added to the JVM stack of the thread. When the method is ended,
the stack frame is removed. It is used to store data and partial
results, as well as to perform dynamic linking, return values for
methods, and dispatch exceptions.
Each stack frame has the reference for local variable array, Operand
stack, and runtime constant pool of a class where the method being
executed belongs. The size of local variable array and Operand stack is
determined while compiling. Therefore, the size of stack frame is fixed
according to the method.
The size of Stack can be initialized using
-Xssn , where n is size prefixed by m or g
It consists of three parts
-
Operand Stack
-
Local Variable Array
-
Frame Data / Run-time constant pool reference
Operand Stack
-
This stack is used by the bytecode instructions for handling
parameters. This stack is also used to pass parameters in a (java)
method call and to get the result of the called method at the top of
the stack of the calling method. -
JVM uses operand stack as work space like rough work or we can say
for storing intermediate calculation’s result. -
Operand stack is organized as array of words like local variable
array.-
But this is not accessed by using index like local variable
array. -
Rather it is accessed by some instructions that can push the
value to the operand stack and some instructions that can pop
values from operand stack and some instructions that can perform
required operations.
-
-
An actual workspace of a method. Each method exchanges data between
the Operand stack and the local variable array and pushes or pops
other method invoke results. The necessary size of the Operand stack
space can be determined during compiling. Therefore, the size of the
Operand stack can also be determined during compiling.
Local variable array
-
This array contains all the local variables in a scope of the
current method.-
It can hold values of
-
primitive types
-
reference and
-
returnAddress
-
-
-
The size of this array is computed at compilation time.
-
The Java Virtual Machine uses local variables to pass parameters on
method invocation, the array of the called method is created from
the operand stack of the calling method. -
The local variables part of stack frame is organized as a zero-based
array of words. -
It contains all parameters and local variables of the method.
-
Each slot or entry in the array is of 4 Bytes.
-
Values of type int, float, and reference occupy 1 entry or slot in
the array i.e. 4 bytes. -
Values of double and long occupy 2 consecutive entries in the array
i.e. 8 bytes total. -
Byte, short and char values will be converted to int type before
storing and occupy 1 slot i.e. 4 Bytes. -
But the way of storing Boolean values is varied from jvm to jvm. But
most of the jvm gives 1 slot for Boolean values in the local
variable array. -
The parameters are placed into the local variable array first, in
the order in which they are
declared. -
It has an index starting from 0. 0 is the reference of a class
instance where the method belongs. From 1, the parameters sent to
the method are saved. After the method parameters, the local
variables of the method are saved.
The Java Virtual Machine uses local variables to pass parameters on
method invocation. On class method invocation, any parameters are passed
in consecutive local variables starting from local variable 0. On
instance method invocation, local variable 0 is always used to pass a
reference to the object on which the instance method is being invoked
(this in the Java programming language). Any parameters are subsequently
passed in consecutive local variables starting from local variable 1.
Run-time constant pool reference
-
Reference to the constant pool of the current class of
the current method being executed. -
It contains all symbolic reference (constant pool resolution) and
normal method return related to that particular method. -
It is used by the JVM to translate symbolic method/variable
reference (ex: myInstance.method()) to the real memory reference. -
It also contains a reference to Exception table which provide the
corresponding catch block information in the case of exceptions.
Native Method stacks
-
A stack for native code written in a language other than Java. In
other words, it is a stack used to execute C/C++ codes invoked
through JNI (Java Native Interface). According to the language, a C
stack or C++ stack is created. -
JVM that supports native methods will have native method stacks. It
is used for native methods and created per thread. -
If the native methods cannot be loaded by a JVM then it need not
have native method stacks. -
Memory size is managed similar to general JVM stacks like fixed or
dynamic. JVM will throw StackOverflowError or OutOfMemoryError
accordingly. -
Also known as C Stacks
-
Eg. – Loading a DLL in the Java Application
Execution Engine
-
The bytecode which is assigned to the Runtime Data Areas in the
JVM via class loader is executed by the Execution Engine. The
Execution Engine reads the bytecode and executes it piece by piece
in the unit of instruction -
Each command of the bytecode consists of
-
A 1-byte OpCode and
-
Additional Operand.
-
-
The execution engine gets one OpCode and execute task with the
Operand, and then executes the next OpCode. -
Contains
-
Interpreter
-
Just in Time Complier
-
Garbage Collector
-
But the Java Bytecode is written in a language that a human can
understand, rather than in the language that the machine directly
executes. Therefore, the execution engine must change the bytecode to
the language that can be executed by the machine in the JVM. The
bytecode can be changed to the suitable language in one of two ways.
Interpreter
-
Reads, interprets and executes the bytecode instructions one by one.
-
It can quickly interpret one bytecode, but slowly executes the
interpreted result. -
Depending on the bytecode instruction, it finds out what native
operation has to be done and executes that native operation by using
native method interface which interfaces the native method libraries
that are present in the JVM-
The native methods are present in JRE bin folder
-
These are the platform-specific native libraries that are used
by the execution engine -
On Windows - .dll files
-
On Unix - .so or
-
JIT (Just-In-Time) compiler
-
The JIT Compiler neutralizes the disadvantage of the interpreter.
-
The Execution Engine will be using the help of the interpreter in
converting bytecode, but when it finds repeated code it uses the JIT
compiler, which compiles the entire bytecode and changes it to
native code.-
After that, the execution engine no longer interprets the
method. The native code will be used directly for repeated
method calls, which improve the performance of the system. -
Execution in native code is much faster than interpreting
instructions one by one. -
The compiled code can be executed quickly since the native code
is stored in the cache.
-
-
It uses
Intermediate Code generator
Produces intermediate code
Code Optimizer
Responsible for optimizing the intermediate code generated above
Target Code Generator
Responsible for Generating Machine Code or Native Code
(Hotspot) Profiler
A special component, responsible for finding hotspots, i.e. whether the method is called
multiple times or not.
Garbage Collector
-
Garbage collection is the process by which the JVM collects and
removes unreferneced objects (unused objects) from the heap to
reclaim heap space. -
Garbage Collection can be triggered by
calling System.gc(), but the execution is
not guaranteed.
Java Native Interface (JNI)
JNI is an interface that connects the JVM with the native method
libraries for executing native methods. It can be used to write the Java
native methods when an application cannot be written purely in Java.
Native Method Libraries
It is a collection of the native (host OS) method libraries which is
required for the Execution Engine
Performance
The most important JVM Components related to performance tuning are:
-
Heap
-
JIT (Just In Time) Compiler and
-
Garbage collector
All objects are stored in the heap, and the garbage collector manages
the heap at JVM initialization.
There are many VM (JVM) options for:
-
Increasing and decreasing the heap size for managing object for best
performance. -
Selecting different garbage collectors, depending on your requirement.
Meanwhile, as for the JIT Compiler:
-
The JIT Compiler compiles bytecode to machine code at runtime and
improves the performance of Java applications. -
JIT Compiler tuning is rarely needed for newer versions of the JVM.

Summary
First is the class loader subsystem second is the runtime data areas
third is the execution engine. Class loader subsystem has load, link and
initialize phases.
Load is for the class loaders – Bootstrap(rt.jar), Extension (lib/ext)
and Application (-cp).
Link has three different steps Verify, Prepare and Resolve
Initialize runs the static initializers
Runtime data have five different data areas which are basically the
memory space allocated for JVM
Metadata for class data
Heap for object data
JVM Stack per thread to keep track of currently executing method and its
data
PC registers per thread, the program counters that knows what execution
and what operation to execute next
Native methods stacks corresponding to native methods used by the
application
Execution engine has the interpreter, just-in-time compiler JIT
compiler, hotspot profiler / hotspot VM
and garbage collector
It interfaces with the native method libraries through Java Native
interface
Java Commands
Questions
Constant Pool
-
An area that corresponds to the constant_pool table in the class
file format. -
This area is included in the method area.
-
It plays the most core role in JVM operation. Therefore, the JVM
specification separately describes its importance. -
As well as the constant of each class and
interface, it contains all references for methods and fields. -
In short, when a method or field is referred to,
the JVM searches the actual address of the method or field on the
memory by using the runtime constant pool.
Important Commands
-
Metaspace
-
-XX:MaxMetaspaceSize=512m
-
-XX:MaxPermSize=256m
-
-
PermGen
- -XX:PermSize=256m
-
Heap Size
-
Following is for Eclipse Helios/Juno/Kepler:
-
Right mouse click on
-
Run As - Run Configuration - Arguments - Vm Arguments,
-
then add this
-
-Xmx2048m
-
-
JVM Stack
By default for development JVM uses small size and small config for
other performance related features. But for production you can tuning
e.g. (In addition it Application Server specific config can exist) ->
(If there still isn’t enough memory to satisfy the request and the heap
has already reached the maximum size, an OutOfMemoryError will occur)
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)
**https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html#BABCBGHF
**
-
Configure your JVM based on your application requirements. Explicitly
specify the heap size for the JVM when running the application. The
memory allocation process is also expensive, so allocate a reasonable
initial and maximum amount of memory for the heap. If you know it will
not make sense to start with a small initial heap size from the
beginning, the JVM will extend this memory space. Specifying the
memory options with the following options:-
Initial heap size -Xms512m – set the initial heap size to 512
megabytes. -
Maximum heap size -Xmx1024m – set the maximum heap size to 1024
megabytes. -
Thread stack size -Xss128m – set the thread stack size to 128
megabytes. -
Young generation size -Xmn256m – set the young generation size to
256 megabytes.
-
-
If a Java application crashes with an OutOfMemoryError and you need
some extra info to detect the leak, run the process with
the –XX:HeapDumpOnOutOfMemory parameter, which will create a heap dump
file when this error happens next time. -
Use the -verbose:gc option to get the garbage collection output. Each
time a garbage collection takes place, an output will be generated.
Check
https://www.tutorialspoint.com/java/java_jvm.htm
https://dzone.com/articles/java-memory-architecture-model-garbage-collection
https://javatutorial.net/java-increase-memory
JVM ( java virtual machine) architecture –
tutorial
https://youtu.be/dncpVFP1JeQ?t=19m14s
Garbage collection in Java, with Animation and discussion of G1
GCs
References
Official (authoritative):
- The Java Virtual Machine Specification (Java SE 17) — https://docs.oracle.com/javase/specs/jvms/se17/html/
- The Java Language Specification — https://docs.oracle.com/javase/specs/
- HotSpot VM / GC Tuning Guide — https://docs.oracle.com/en/java/javase/17/gctuning/
- JEP 122 — Remove the Permanent Generation (PermGen → Metaspace, Java 8) — https://openjdk.org/jeps/122
Deep-dive / learning:
- “Java Performance: The Definitive Guide” — Scott Oaks (O’Reilly)
- “The Java Virtual Machine Specification” (book) — Lindholm, Yellin et al.
- Aleksey Shipilëv’s JVM/GC articles — https://shipilev.net/
- Baeldung JVM series — https://www.baeldung.com/jvm-series