Overall process of Java
compilation could be simply summarised as below.
Java Compiler
converts source code into JVM
readable bytecodes
. Java Virtual Machine
, shortly JVM
reads the bytecodes
and executes it via interpreting the provided bytecodes
or compiling thebytecodes
into machine codes
. Java
's portability in which theJava
compiled codes could function in the machines all varying Operating System
, OS
, deeply underlie the above Java
compilation processes and the following sub-chapters and paragraphs will discuss the above steps into a lot greater detail.
Like any other programming language that involves compiling as its core basis of such programming language perhaps C
, Java
may follow an identical compiling process.
Lexical Analysis
tokens
. Syntax Analysis (parse)
AST
(Abstract Syntax Tree)
.Semantic Analysis
Code Generation
in the Java
context,Java Compiler
in JDK (Java Development Kit)
is responsible for compiling the Java
source code. The compiler transforms source code into a bytecode
, the intermediate code
specifically designed for JVM
rather than directly into binary or machine-readable code. Java
's portability stems from this design, as the JVM
is OS
-independent. The JVM
acts as an interface that translates the bytecode
into low-level machine-readable instructions
, allowing Java
programs to run seamlessly across different operating systems
without modification.
JVM
is responsible for executing the compiled bytecode
JVM
is structured as below and this follows a suggested JVM
specification from Oracle
.
Class Loader
Execution Engine
Runtime Data Areas
Native Method Interface
Native Method Library
and simply JVM
executes a compiled bytecode
followed by these steps:
Class Loader
loads requested classes
into the Runtime Memory Areas
.Execution Engine
either interprets and compiles the bytecode
.Native Method Interface
, JVM
invokes Native Method Library
that is directly responsible for executing the code at the hardware level.the following paragraphs will discuss these processes in greater detail.
Java
dynamically loads classes
in which by doing so, it mitigates the chance of loading too many unnecessary classes, thereby mitigating the risk of overexploiting memories that are directly leading to memory exceptions. Class Loader
is the JVM
component that is responsible for this dynamic loading
.
Class Loader
has unique attributes and one that is very closely related to its loading mechanism could be a delegation hierarchy
in which its loading
responsibility is passed over to other class loaders
with higher hierarchies.
class loaders
forming a hierarchy notably are
Bootstrap Class Loader
Extension Class Loader
Application Class Loader
and these class loaders
have different responsibilities in which
Bootstrap Class Loader
Java API
(classes in machine codes).Extension Class Loader
JRE
. Application Class Loader
this overall could be graphically explained below.
if JVM
has to load classes that are not already loaded in Runtime Data Area
, Class Loader
loads classes
in the following steps.
Loading
Linking
Initialising
load a symbolic reference of a class or an interface into the Runtime Data Area
, specifically in Method Area
.
classes
or interfaces
is structurally correct.classes
or interfaces
and allocate a memory address
for classes
, interfaces
, and static fields, and set a default value to these fields. concrete value
or a memory address
to the concerned symbolic reference in Method Area
. execute an initialising method in a class or an interface. (run a constructor
and a static field) and set static fields to the user-defined values from a default value.
Method Area
is a memory space
shared by all threads
and is created when the JVM
starts. It stores runtime constant pools
, field
and method information
, static variables
, and the bytecode
of methods for each class
and interface
that the JVM
loads. The implementation of the method area
can vary between different JVM
vendors. In Oracle's HotSpot JVM
, this area is commonly referred to as the Permanent Area or Permanent Generation (PermGen). Garbage collection for the method area is optional and up to the JVM
vendor.
Runtime Constant Pool
corresponds to the constant_pool table
in the class file format. Although it is part of the method area
, it plays such a crucial role in the JVM
's operation that the JVM
specification highlights it separately. It contains not only constants for each class
and interface
but also all references to methods and fields. In other words, when a method or field is referenced, the JVM
uses the runtime constant pool
to locate the actual memory address
of that method or field.
Every JVM
thread has a private JVM stack
and the stack
becomes created at the same time as the thread
. A JVM
stack
only stores frames
where its push
and pop
command only push
and pop
the frames
. A frame
is a logically varying stack to a JVM
stack
as it is created upon a method invocation. It handles method execution behind the scenes in which a frame
stores parameters, local variables, and partial computations, as well as return values for methods.
It is a memory space
dedicated for objects
or instances
and arrays
. It is shared across all JVM
threads and also a target for a GC (Garbage Collection)
in which unused memories in heap
will be automatically disallocated.
Each JVM thread
has its own pc (program counter) register
and pc register
stores the line number or address of the currently executing threads
.
It is a stack
for native code
written in languages other than Java
. In other words, it is a stack
used to execute code such as C/C++
, which is called through the Java Native Interface
. A language compatible stack
becomes created.
once classes
and interfaces
become loaded into the Runtime Data Area
, JVM
lets its Execution Engine
read its bytecodes
and then executes the code by either providing the corresponding machine codes
or directly interpreting and executing the bytecodes
.
overall Execution Engine
is composed of:
Interpreter
JIT compiler
Garbage Collection
Interpreter
reads the bytecodes
line by line and then executes it. Interpreter
's line-by-line interpretation may be quick however, interpreting the identical bytecodes
overall may slow the entire interpreting process and its execution.
JIT
is a component that compiles the entire bytecode
into a native instruction set
of the host CPU at runtime or Just in Time
.
it resolves the above innate inefficiencies that come with the interpreter
, hence JVM
at some point in time while interpreting will execute its JIT Compiler
. JIT Compiler
may also cache repetitive bytecodes
so that the interpreter
can directly access the corresponding native codes
to the repetitive bytecodes
, thereby enhancing the overall performance.
a component that automatically manages Java
's memory. GC
, specifically finds a data that is no longer used in the Heap
memory, and frees the memory space.
in C
or C++
, it was soley a developer's responsibility to free no longer accessed memories. However, in Java
, Execution Engine
in JVM
frees it for the developers' convenience.
Native Method Interface
serves as a bridge between the JVM
and native libraries, typically written in C
or C++
, that are essential for program execution. It enables the JVM
to call native methods and also allows external native libraries to interact with the JVM
, providing support for hardware-specific operations.
Native Method Library
contains a set of native libraries that support the execution of native methods. These libraries, written in languages such as C
or C++
, provide the functionality needed for tasks that require direct interaction with the underlying hardware or operating system
.