Being a java developer we should know the details of ‘How a java class file gets processed by JVM internally’. In this article on ‘JVM Architecture and Class Loaders Java’ we will learn about how JVM handles a .class file and does the internal processing to generate the output. However It is just to remind you that the JVM(Java virtual Machine) is responsible to process the compiled .class file in byte-code form. Hence our title for this article is “JVM Architecture and Class Loaders Java”. Moreover, along with the internal processing of a class file we will also learn the internal Architecture of the Java Virtual Machine in detail.
JVM contains three primary sections :
1. Class Loaders
2. Memory Area
3. Execution Engine
What does the Class Loaders do?
When we compile a source (.java) file, it gets converted into byte code as a .class file. Furthermore, when we try to use this class in our program, the class loader loads it into the main memory. Normally the class that contains the main() method is the first class to be loaded into the memory. The class loading process happens in three phases.
3 Phases Of Class Loading
Loading phase involves accepting the binary representation (bytecode) of a class or interface with a specific name, and generating the original class or interface from that. The JVM uses the ClassLoader.loadClass() method for loading the class into memory.
Once a class is loaded into the memory, it undergoes the linking process. Linking a class or interface involves combining the different elements and dependencies of the program together. As the name suggests making required links with each other.
This is the final stage of class loading. Initialization involves executing the initialization code of the class or interface. This can include calling the class’s constructor, executing the static block, and assigning values to all the static variables.
3 Class Loaders in Java
The class loaders load the compiled class file. Class loader system contains 3 types of class loaders.
1. Bootstrap class Loader (BCL)
2. Extension class Loader (ECL)
3. Application class Loader (ACL)
Bootstrap class loader
Bootstrap class Loader is responsible for loading all core java API classes. These are all classes that exist inside rt.jar which are available in all JVMs by default. Bootstrap class Loader loads classes from bootstrap class path. However it’s implementation is in native languages(C, C++) but not in java.
Bootstrap Class Path is JDK/JRE/lib
Extension class loader
Extension Class Loader is a child class of Bootstrap class loader which is responsible for loading all classes from the extension class path in java. However, it’s implementation is in java only. The Extension Class Path is : JDK/JRE/lib/ext
Application class loader
Application Class Loader is a child class of Extension class loader which is responsible for loading classes from application class-path. It’s implementation is also in java. The Application class path is our environment class path.
How does a class loader work?
Class loaders follow Delegation Hierarchy Principle. When JVM comes across a particular class, first of all it checks whether the corresponding .class file is already loaded or not. If it is already loaded in Method area, then the JVM considers that class is loaded without fail. But If it is not loaded, JVM requests class loader sub-system to load that particular class accordingly.
The class loader sub-system handovers the request to application class loader. Further Application class loader delegates the request to extension class loader which in turn delegates request to bootstrap class loader. Now the Bootstrap Class Loader will search in the bootstrap class path, if it is available then the corresponding .class will be loaded by Bootstrap Class Loader. If it is not available then Bootstrap Class Loader delegates the request to extension class loader.
Further, Extension Class Loader will search in extension class path. if it is available then it will be loaded otherwise Extension Class Loader delegates the request to Application Class Loader subsequently. Now Application Class Loader will search in application class path. If it is available, then it will be loaded otherwise in the end we will get runtime exception saying NoClassDefFoundError or ClassNotFoundException.
*** Loader Priority BCL>ECL>ACL
For example, Methods to get class loaders are as below :
String.class.getClassLoader(); Test.class.getClassLoader(); Customer.class.getClassLoader();
***CustomizedClassLoader extends java.lang.ClassLoader : while developing web server/application server we can use it to customize class loading mechanism.
JVM Memory Area
The division of total Memory area of JVM is in 5 parts :
1. Method Area :
In the method area, One area will be allocated for each JVM. It will be created at JVM startup. Class level binary information & static variables reside in this area. Also Constant pools will be saved inside method area. Further It can be accessed by multiple threads simultaneously, therefore it is not thread-safe.
2. Heap Area :
One area will be allocated for each JVM. It will be created at JVM startup. Objects reside in this area. It can be accessed by multiple threads simultaneously, therefore it is also not thread-safe.
How can we find allocated heap area ?
Runtime r = Runtime.getRuntime(); r.maxMemory(); r.initialMemory(); r.freeMemory(); Runtime is inside java.lang package is a Singleton class.
How to set maximum & minimum heap sizes ?
1. By using command prompt execution of program :
java -Xmx512m JavaProgramFileName enter
java -Xms64m JavaProgramFileName enter
Where Xmx indicates Maximum Memory & Xms indicates Minimum Memory. Heap memory is finite memory but based on our requirement we can set max & min heap sizes.
2. By Setting ‘JAVA_OPTS’ as a system variable
After that in a command prompt run the following command:
SET JAVA_OPTS=”-Xms256m -Xmx512m”
This setting indicates
allocating minimum 256MBs of heap
allocating maximum 512MBs of heap
3. Stack Area :
It is available per thread unlike Method & Heap area as they are one per JVM. Each entry in stack is called Stack frame or activation record. Also it is thread-safe as it allocates one memory for each thread. Furthermore, Each stack frame has three parts : local variable array, operand stack and frame data.
Local Variable Array : It contains values of local variables & method parameters.
Operand Stack : JVM uses it as workspace, some instruction push the values to it & some pop from it & some other to performs arithmetic operations.
Frame Data : It contains all symbolic references related to the method. It also contains reference of exception related to method.
4. PC Registers :
(Program Counter Registers) : Internally used by JVM. For every thread JVM creates a separate PC register. In brief PC register contains address of currently executing threads.
5. Native Method Stacks :
For every thread JVM creates a separate native method stack if its native method call.
****Note : Method Area, Heap Area, Stack Area are also considered as important memory areas as programmers point of view. Method Area, Heap area are for per JVM whereas Stack area, PC register & the native method stack are for per thread.
♦ Static Variables are stored in Method area ♦ Instance Variables are stored in Heap area ♦ Local Variables are stored in Stack area
It is a central component of JVM and responsible for executing .class files. It mainly contains two parts : Interpreter & JIT compiler
Interpreter reads & interprets bytecode, converts it into machine code/native code line by line. Because of line by line performance of system goes down. Then JIT compiler comes into picture in jdk 1.1 version.
JIT Compiler :
The primary purpose of JIT compiler is to improve performance. In fact, Internally it maintains a separate count for every method. Whenever JVM comes across any method call, first that method is interpreted normally by the interpreter and JIT compiler increments the corresponding count variable accordingly.
This process continues for every method. Once if any method count reaches threshold value then JIT compiler identifies that the method is repeatedly used method. We also call that method as hotspot for the JIT compiler. Then JIT Compiler compiles that method immediately & generates corresponding native code. Next time JVM comes across that method call, then JVM uses native code directly & executes it instead of interpreting it once again so that performance of the system will be improved. However the threshold count varies from JVM to JVM.
♦ Some advanced JIT compilers recompile generated native code if count reached threshold value second time so that more optimized machine code can be generated. Internally profiler (which is the part of JIT compiler) is responsible to identify hot-spots.
****Note : => JVM interprets total program at-least once.
However, JIT compilation is applicable only for repeatedly required methods not for every method.
Additionally JIT Compiler has intermediate code generator, code optimizer, target code generator & machine code generator in its whole compilation process.
Garbage Collection is the process of reclaiming the runtime unused memory automatically by destroying them. The Garbage Collector (GC) collects and removes unreferenced objects from the heap area.
Garbage collection makes Java memory efficient because it removes the unreferenced objects from heap memory and makes free space for new objects. It involves two phases: Mark & Sweep. In Mark phase, the Garbage Collector identifies the unused objects in memory, whereas in Sweep phase, the Garbage Collector removes the objects identified during the mark phase.
Garbage Collections doesn’t need to be handled separately as it is done automatically by the JVM at regular intervals. It can also be triggered by calling System.gc(), but the execution is not guaranteed.
JNI (Java Native interface) :
JNI acts as mediator between java method calls & corresponding native libraries. Additionally JNI is responsible to provide information about native libraries to the JVM.
Native method library : In brief It just holds native libraries information.
This is all about “JVM Architecture and Class Loaders Java”. We have discussed each & every section of JVM and respective section’s role in processing a java class file. Hope that all the points of the title “JVM Architecture and Class Loaders Java” is covered in this article. Moreover, If you want to learn more demanding topics in Core Java kindly visit our Core Java section.
What is difference between PermGen & Metaspace?
PermGen (JDK 7 & lower versions)
PermGen is a special heap space separated from the main memory heap. Moreover, the full form of the PermGen is the Permanent Generation. JVM uses this space to keep track of metadata such as loaded classes. Additionally, the JVM stores all the static content in this space such as all the static methods, primitive variables, and references to the static objects.
The default maximum memory size for 32-bit JVM is 64 MB and for the 64-bit version its 82 MB. However, we can change the default size with the JVM options. When application tries to load unusual number of classes, we may see “java.lang.OutOfMemoryError : PermGen space”
Most importantly, Oracle has completely removed this memory space in the JDK 8 release.
Metaspace (JDK 8 & higher versions)
Metaspace is a new memory space – starting from the Java 8 version. Specifically, it has completely replaced the older PermGen memory space. The most significant difference is how it handles memory allocation. It is a part of native memory region. Moreover, Metaspace by default auto increases its size depending on the underlying OS. Here, the garbage collection is automatically triggered when the class metadata usage reaches its maximum metaspace size. Moreover, it does better garbage collection than PermGen. Hence, with this improvement, JVM reduces the chance to get the java.lang.OutOfMemory error.