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 Analysistokens. Syntax Analysis (parse)AST (Abstract Syntax Tree).Semantic AnalysisCode Generationin 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 LoaderExecution EngineRuntime Data AreasNative Method InterfaceNative Method Libraryand 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 LoaderExtension Class LoaderApplication Class Loaderand 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.
LoadingLinkingInitialisingload 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:
InterpreterJIT compilerGarbage CollectionInterpreter 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.