Internal Structure of the JVM

Thilini Weerasinghe
8 min readMay 6, 2021

In my previous article I have discuss about some basic things about the JVM and today I am going to explain about the high level explanation about the internal structure of the JVM.

JVM has main three parts. They are,

  1. Class Loader Subsystem
  2. Memory Area Subsystem and
  3. Execution Engine Subsystem

Let’s explain this internal process using simple real-world scenario. Think, if we want to get goods from the supermarket. First we have to go for the good’s rack and take the particular goods (load) and put them into our carts (store). After that we pay bill and take them to our home (execute). Like that class loader is responsible for loading tasks, memory area for the storing purposes and at last execution engine is responsible to execute the program.

Lets go in deep one by one..

JVM Architecture . source: https://techvidvan.com/tutorials/java-virtual-machine/
  1. Class Loader Subsystem

It loads the class file information and data types information into the memory area. The process that class loader is loading class to the RAM is known as the Dynamic class loading.There are four types of class loaders.

  1. Bootstrap class loader
  2. Extension class loader
  3. Application class loader
  4. Custom defined class loader
  • Bootstrap class loader

This type of class loader is responsible for loading standard JDK classes from rt.jar file such as core java file from the bootstrap path. This is implemented in native languages like C/C++ and work as the head or parent among the all class loader.

ex: java.lang.*package classes , $JAVA_HOME/jre/lib directory

  • Extension class loader

As it is mentioned in the name, it loads the class from the directory called extension directory. If the requested class was not available in the bootsrap path then it moves back to the extension class loader and check whether it has that particular class. As an example if the class request security features it loads security extension from the directory. They are implemented in using sun.misc.Launcher$ExtClassLoader class.

ex: $JAVA_HOME/jre/lib/ext or any other directory which has java.ext.dirs system property.

  • Application / System class loader

If the class file are not available in the extension path, then move to the application class loader and check whether file is available on the system path. It internally uses environment variable which mapped java.class.path. This is the final class loader which checks the availability of .class file and if any of these class loader couldn’t find it, then it will throw an runtime exception called java.lang.classNotFound exception.

  • User defined / custom class loader

Except the above mentioned three class loader, developer can create own class loader in their code. This kind of approaches are mainly used in web application servers such as Tomcat to run its applications independently.

Each an every class loader has its own namespace to store the loaded class. A class loader searches the class file based on its FQCN( Fully Qualified Class Name) stored in the namespace to ensure whether it has already loaded or not. If the class has unique FQCN and different namespace, it is considered as a different class and it has loaded by another class.

Principle of class loader

Each an every class loader should follow these four principle.

  • Visibility Principle

All the child class loaders should have ability to see the class loaded by its parent class loader and the parent class loader hasn’t right to see the class which is loaded by the child class loader.

  • Uniqueness Principle

It doesn’t allow for the duplicate loading of a class. It means a class already loaded by the parent class should not again loaded by the child class loader.

  • Delegation Hierarchy Principle
Delegation Hierarchy of class loader source: https://javarevisited.blogspot.com/2012/12/how-classloader-works-in-java.html

To ensure the above mentioned principle it stats loading a loaded request from its child class loader to parent class loader. Therefore request is going through the application class loader -> extension class loader -> bootstrap class loader. After the request is reached to the bootstrap class loader, then the searching process is started. If the requested class found in there it loads it and if not the request is passed to the extension class loader to check the availability. If it available there it loads the file and if not the request is sent to the application class loader to check the system path. If the file is available in there class is loaded and if not, it throw a runtime exception called java.lang.classNotFound exception.

  • No Unloading Principle

Even though a class loader is able to load the class, it won’t be able to unload a loaded class. The only thing it can do it, delete the loaded class and then create a new class loader.

These are the needed background knowledge for the class loader and it has main three function. They are, 1. Loading 2. Linking and 3. Initialization. Let’s go through the each step one by one.

i. Loading

In loading phase it loads the class file into the memory area. In here initially it loads the main class(class which contains main()). After that it loads other classes according to the reference. In loading phase it reads four things,

  • read the fully qualified class name
  • read the immediate parent class information
  • read the instance variable information
  • check whether it is a class, interface or enum(enum is a special type of class which contains group of constants i.e unchangeable variable like final)

ii. Linking

It goes across the three steps named as verification, preparation and resolution. It has several properties..

  • Before moving to the liking phase, all the classes and interfaces should be loaded completely.
  • It must verify and prepare before move to the initialization phase.
  • If there is a particular error occurred during the linking phase, it is thrown at a point where

Let’s go deep into the each steps in the linking phase.

  • Verification

It check whether execution of class file is secured or not. In JVM it has Bytecode Verifier to complete that verification task. It mainly check whether,

  • It comes from the valid compiler
  • It has correct structure and
  • It has correct format

If any of them are fail to verify, then it throws a runtime exception called verifier exception.

  • Preparation

In preparation phase, it assign default value for every static and instance variable. As an example if it is a boolean= false , object= NULL and int =0 for that. Also it allocates memory for any data structures and static storage used by JVM such as method tables.

  • Resolution

Last step in the linking phase is resolution. In here JVM replace a symbolic link to the direct link. It replaced the object with the specific memory location value which is referred by the object.

iii. Initialization

In this phase it assign initial value for the variable and execute the static block. It is the final phase in the class loader subsystem. As JVM is multi-threaded system, initialization should be happened carefully with proper synchronization to avoid the initialization of other class/interface at same time. Loading and linking can be executed in any order, but all the classes should initialize before its active use.

2.Memory Area / Runtime Data Area Subsystem

For every successful loaded class, JVM creates a Class Type object to represent the class file in the Heap and then it uses to read all the class level information such as class name, variable and method info, parent name etc. This subsystem has five main parts.

  • Memory/Method Area (Only one per JVM)

It stores all the information about class information and type information such as;

  • Runtime constant pool
  • Class loader reference
  • Field data: name, type, attributes, modifier (per field)
  • Method data: name, return type, modifier, attributes, parameter types (per method)
  • Method code: byte code,local variable size
  • Heap (Only one per JVM)

It store information about the objects and their related instance variable and arrays. Mainly Garbage collector is always targeting this part of the memory area.

  • Stack (Only one per thread)

It stores information about the methods. When a thread stats it works, it creates a separated stack frame for each thread and after executing that particular thread/method, it pops that frame and free up the frame. Not only that but also frame was removed if the uncaught exception was thrown in the method invocation. A stack frame has reference to the local variable array, operand stack and the runtime constant pool of a class. The size of local variable array and Operand stack is determined while compiling. Therefore, the size of stack frame is fixed according to the method.

  • A size of the stack can be dynamic or fixed value. If the thread required a larger stack than the value it already allowed, then it throws StackOverFlow Error.
  • If a particular thread required a new stack frame for its execution and there isn’t any enough memory to allocate for the frame, then it throws OutOfMemory Error.
  • PC (Program Counter) Register (Only one per thread)

If the method is not a native method, PC Register is kept information about its execution. When a thread is started its execution a separate PC register is created to hold the address of current execution.PC register is undefined in a particular time that the native method is available. After the execution is finished, again PC register is updated with the next execution.

  • Native Method Area (Only one per thread)

It is responsible to provide facility to store the information about the native method. In here a separated native stack is created to store native method information. Native methods are mostly written on non-java language C/C++ and invoke from the JNI (Java Native Interface).

3. Execution Engine Subsystem

Execution of the loaded class is begun in this subsystem. It reads the byte code line by line and through getting data from above described memory area. It has three parts named as Interpreter, JIT Compiler and Garbage Collector.

  • Interpreter

It executes the instructions line by line. Disadvantage of this is, if there is a method has multiple calling, in each an every time of this method calling, it reads the same code instructions and it is waste of time and direct to low efficiency.

  • JIT (Just In Time) Compiler

As mentioned in before, if there is a method called multiple times, JIT compiler provides high efficiency execution mechanism for that. In here it compile the entire byte code (in one time.Not line by line) into native code (machine code) and then when the method calls in many places,it directly assign created native code instead of that and execute the method. These native codes are stored in the cache.

  • Garbage Collector

Garbage collector (GC) is responsible for destroying unused object from the heap area. We can consider an object as unused, if and only if it has following features.

  • NULL

JVM consider an object is in alive as long as it is referenced. Once it is no, it can’t be reached by application code and then GC removed that object to claim the unused memory.

  • Island of isolation

If there is two object reference to each other internally and but they are null externally . Then GC removed that objects too.

Inspite of these main three subsystem there are two section in the JVM named as Java Native Interface (JNI) and Native Method Libraries.

Java Native Interface (JNI)

It is used to interact with the native method libraries that are required for execution of native method.

Native Method Libraries

It is a collection of native method libraries.

Now we have described about the internal structure of the JVM in detail. As a summary JVM is responsible for converting byte code into machine code and it is not a one process. To complete this function it goes through several sub processes. To complete that sub processes there are three subsystem in the JVM to responsible for that. Class Loader, Memory Area and Execution Engine are those three system and this article has explained each and every phase clearly.

Stay safe & Learn new things!!!

--

--

Thilini Weerasinghe

Currently working as an Associate Software Engineer at Virtusa. Has completed degree in B.Sc (Hons) Computing & Information Systems. After all I am a Human...