Hey Guys! In this post, we will learn how java code gets loaded, compiled and executed in JVM. We will walk through the internal working of various parts of JVM.
JVM is an abstract machine. It is just a specification how JAVA code can be analyzed, compiled and executed on a Virtual Machine. JRE is the implementation of JVM which actually provides the environment for Java code to compile and execute.
When we write a Java code, it is saved in a .java file. After compilation, .java is converted to .class file. When we actually execute the file, .class file is loaded into JVM, its analyzed and finally gets executed. This process can be visualized in the figure below.
Classloader loads .class file in the JVM and has three main responsibilities:
- Loading Classloader loads the .class into JVM. JVM creates its binary and stores its meta in the method area. This meta includes fully qualified domain name of the class and information related to parent class, Modifier, variables, constants etc. After loading, JVM creates an Object class predefined in Java.lang package in the heap area. Further operations can be done on this Object.
- Linking First, it performs verification of .class file, it makes sanity checks to verify the formatting and validates whether the file is generated via valid compiler. Second, It allocates memory for all the class variables and initializes them. This step is called as preparation. Third, it replaces symbolic references with direct references. This is known as resolution.
- Initialization All static variables are assigned to their respective values. All static blocks are executed in sequence of their definition.
Classloaders have three types.
- Bootstrap classloaders: It loads classes from the bootstrap path, i.e JAVA_HOME/jre/lib directory.
- Extension class loader: It is a child of bootstrap class loader. It is responsible for loading classes from JAVA_HOME/jre/lib/ext or extension path.
- System/Application class loader: It is a child of extension class loader. It is responsible to load classes from application class path.
Classloaders follow delegation-Hierarchy. System classloader delegate request to Extension classloader and inturn to Bootstrap classloader. If Bootstrap path does not have class then request is transferred to Extension and then to System classloader. If class is not found in System classloader, Jvm throws java.lang.ClassNotFoundException.
JVM Memory Model
- Method Area: All class level variables are stored here with all the static blocks. There is only one method area per JVM and it is shared among all the classes.
- Heap Area: All the instance variables and runtime objects are stored in heap area. There is only one heap area per JVM and it is not thread safe.
- Stack Area: Every threads has its own stack area. Every method call will be stored in a stack frame. This resource is not shared among the threads and hence it is thread safe. Within Stack Area, Local Variable Area holds local variable and its values, Operand stack acts as a runtime workspace for method calls and Frame data consist of all the symbols used like catch, throw etc.
- PC Registers: Every thread has a PC register which holds the address of the currently executing instruction.
- Native Method stacks: holds native method information.
JVM Execution Engine
In the last phase, the bytecode is executed within the JVM within the Execution engine. It reads, interprets and analyzes the byte code and executes it piece by piece.
- Interpreter: It interprets the byte code and executes it. Every time a call is made it interprets the file from the scratch.
- JIT Compiler: This has an advantage over interpreter, as it does not compile again for similar calls, rather it converts bytecode and put that in native stack. Native stack can serve the repeating method calls.
- Garbage Collector: This is responsible for collecting dereferenced object and freeing up space for allocation.
Hope, this interpretation of JVM internals will be helpful in understanding how JVM actually works under the hood.
Happy Learning!!
Relevant Posts: