We write a code in our IDE, How it is being executed? How does it shows the output which we want (not always!)? This question has perplexed many beginner as well as some high level coders. Here, I will try to answer those questions to some extent vis-a-vis JAVA.
So, it’s well established fact that all the dirty work of compiling, executing the code is done by Java Virtual Machine(JVM). But what exactly does JVM consists of? How does it executes a code?
Whatever we write on IDE is present in java source file(.java file). It is then compiled using Java compiler( by javac command). A java class file (.class file) is generated which is then fed to the class loader subsystem.
The whole JVM architecture looks as follows:
It takes .class file and performs three operations on it:
All core Java API classes are loaded by Bootstrap class loader. The classes present inside extension folder such as jdk and jrk files are loaded by Extension class loader. Further Application class loader loads classes from application level and loads it into the class-path.
Here, the class file which is loaded is prepared for execution. Verify operation verifies the syntax. Static variables are allocated memory within prepare block, also those variables are initialized ( Attention:- here the variables are initialized with default values). Further, all symbolic references are replaced with original references from method area while resolve block is being executed.
Finally, the static variables are initialized with the original value assigned and all the static blocks are executed.
Each and every file and operations require a memory area during run-time. JVM provides various run-time data areas.
All .class files are dumped here. It also contains all the static variables.
It consists of all the instance variables or object data.
For every thread, separate run-time stack will be created which resides in stack area. And for every method called, one entry will be stored in the stack, that entry is called stack frame.
Each stack frame consists of 3 parts:
Local variable array:- As the name suggests, all the local variables of a method and their values are stored here.
Upper end stack:- This memory area is used for any intermediate operation within a method.
Frame data:- All symbols used in the method is stored here. Also, if any exception occurs, catch block is stored here.
For every thread, separate PC register is created in this area. A PC register contains the address of next executing instruction of that thread.
Lastly, Native method area holds all native method instructions.
Here, we can easily see, as for each thread a separate run-time stack is allocated in stack area, which implies that stack area is thread safe. While, for whole JVM, there will be only 1 method area and heap area, which implies that both of the aforementioned areas are not thread safe.
Till now, the class is allocated memory and is loaded. All the dirty work of execution of a code is done by this engine. Just like CPU, this executes the program line by line. It also consists of different parts.
It reads, interprets and executes the code line by line.
It comes into action only when there are repeatedly required methods, not for all methods. Profiler does the job of identifying the repeatedly required methods or hotspot methods.
Then there is garbage collector which collects those variables or methods which are unreachable in a code and frees the memory.
At last, there is native method interface or Java native interface(JNI) which simply provides an interface for Native method libraries to be loaded during run-time.
So, this is what makes up JVM and their functions.
Hope, it gives you a basic idea of what sorcery is going on within the machine!! Enjoy.