Inside JVM, JRE, JDK And Their Relationship8 min read
There are several basic terms that often confuse beginners are JVM, JRE, and JDK (including me). From the abbreviation, they look quite the same and it is quite hard to tell them apart. In this article, we are going to disembroil those concepts.
Java Virtual Machine (JVM)
A Java virtual machine (JVM) is a virtual machine that enables a computer to run Java programs as well as programs written in other languages that are also compiled to Java bytecode. JVM runs as an application on top of an operating system and provides an environment for Java programs.
You probably heard somewhere that Java programs are platform-independent and you just need to write the program once and it can be run anywhere regardless of operating system and different hardware according to the Write Once Run Anywhere (WORA) principle. This principle is empowered by Java Virtual Machine.
JVM is an abstract virtual machine, hence there is a variety of JVM implementations. HotSpot is the primary reference for Java VM implementation used by Oracle Java and OpenJDK.
We have learned some basics of JVM, now let’s actually see what’s inside the JVM.
Inside the JVM
Have you noticed, there is always a file with
.class extension that emerged after every time you compile the Java program. This file contains the bytecode, which we have mentioned above. To make it executable, you need to load it to JVM. When JVM executes this program, it will translate the bytecode into platform native code.
The way JVM works is basically as follow, first it loads the bytecode from the
.class extension file, next, it verifies the bytecode whether it is safe or not to avoid data corruption or unpredictable behavior, after verifying, it then executes the bytecode and finally it provides us the Java Runtime Environment (JRE) which we will discern later in this article.
Here are some primary components inside the JVM:
- Class Loader
- Run-Time Data Areas
- Execution Engine
The Class Loader
The first component of JVM we need to consider is the Class Loader, because JVM initially loads the bytecode and this component is used to handle this job. After loading the bytecode, JVM verifies bytecode and then allocates memory for the bytecode. To verify the integrity of the bytecode, the module named Bytecode verifier is involved. It ensures the data to be loaded to the JVM don’t perform any dangerous actions like accessing index out of bounding of the array, accessing private fields and methods of classes and objects.
The runtime data areas
As we can see in the image above, the JVM memory depicts the runtime data areas. There is not just one, but multiple areas and each is used for different purposes:
It also is known as permanent generation space (PermGen), which stores all class-level information such as class names, class variables, method information, and all static variables in your Java program. All JVM threads share this area.
Heap is a tree-based data structure that is usually used for the HeapSort algorithm or Priority Queue, etc…Heap area in JVM is used to store all created objects (instances of classes).
In HotPot, a variation of JVM, the heap area is divided into generations:
- The young generation stores short-lived objects that are created and immediately garbage collected.
- The tenured generation is used to hold objects that persist longer.
A stack is the Last-In-First-Out (LIFO) data structure which is typically used to store local variables and method calls. In Java Virtual Machine, the Stack area does exactly the same things, it is a memory place where methods calls and local variables are stored.
The Program Counter Register (PC Register) holds the address of currently execution instruction.
Native Method Stack
In Java, you probably have a glance at the non-access modifier
native and the
native keyword. The Native Method Stack holds information about native methods that are written in languages other rather than Java, such as C. Whenever you write native methods and involve those in Java with the
native keyword, during the compilation into the machine code, those methods will be kept track on Native Method Stack area.
The Execution Engine
The Execution Engine has responsible for executing the information (the bytecode) which is already stored in the memory areas. It has 3 parts:
- bytecode interpreter: it interprets the bytecode line by line and executes it, hence this process is rather slow.
- just-in-time compiler (JIT Compiler): is a way of executing computer code that involves compilation during the execution of a program – at run time – rather than prior to execution. It translates the bytecode into the machine language while executing the program hence it’s far faster than an interpreter.
- garbage-collector: the garbage collection is an automatic process. You don’t have to worry much about the unused objects stored in the heap because the garbage collector will clean them for you to free up memory.
Native Method Interface
This interface acts as a bridge between your Java program and C/C++, etc…libraries. It enables Java code running in a Java virtual machine to call and be called by native applications and libraries written in other languages such as C, C++, and assembly.
Native Method Libraries
The Native Method Library is the place to implement the native code. It consists of (C/C++) files that are required for the execution of native code.
Java Runtime Environment (JRE)
If a program needs to execute, then in order to perform this, the run time environment which lets a program can be run is essential.
JRE is an execution environment for running Java programs, it includes the Java Virtual Machine (JVM) and Java Class Library (JCL). Java Virtual Machine as we already have stated above.
JCL is a set of dynamically loadable libraries that Java applications can call at run time, it consists of many libraries including input/output, collections, security, classes for parsing XML, user interface toolkits, and many others.
Before Java 11, if you only wanted to run a Java program, JRE was enough for you. However, since Java 11 was released, JRE is no longer downloadable as a separate component. You should always install JDK.
Java Development Kit (JDK)
Finally, JDK is a package to run and develop the Java program, it provides environment and tools for developing, executing, compiling and debugging your program. Core components of JDK include:
- Java Runtime Environment (JRE) as we discussed above.
- Development Tools
Let’s move on to some of the basic tools inside JDK.
Basic Tools in JDK
Basic tools in JDK lets you create and run your Java application, here are some common utilities such as executing, compiling, generating Java docs that you can use them in the command line:
- javac – reads class and interface definitions and compiles them into class files
- java – launches the Java application
- javadoc – generates HTML pages of API documentation from Java source files
- javah – produces C header and source files from a Java class
Remote Method Invocation (RMI) Tools
RMI is an API that provides a mechanism to create distributed applications in java. Remote Method Invocation (RMI) facility lets you make method calls on objects that exist outside your JVM. RMI is an extensive topic, so we don’t go deep in this article. Here are some basic commands that you can do with RMI:
rmicfor generating stub, skeleton for remote objects using the Java Remote Method Protocol (JRMP).
rmicregistry, the RMI registry is a program that associates names with RMI services. A server specifies a name for every remote object it provides.
rmicregistrycreates and starts a remote object registry.
Security Tools in JDK
A Java KeyStore is a repository of security certificates either authorization certificates or public key certificates plus corresponding private keys, used for instance in SSL encryption. Some of its function include:
keytoolis the Key and Certificate Management Tool. It has a lot of commands available for managing cryptographic keys and certificates.
jarsigner– generates signed JAR files by using Keystore information
Internalization Tools in JDK
Internationalization is the process of designing an application so that it can be adapted to various languages and regions without engineering changes.
native2ascii, this tool helps to create localizable applications.
There are many other Standard JDK Tools and Utilities, you can take a look in detail at the Java API’s reference page.
The relationship between JVM, JRE, and JDK
To recap, the following image will help you illustrate the relationship between JVM, JRE, and JDK:
Succinctly, you should remember these abbreviations:
- JVM executes compiled Java programs;
- JRE includes JVM and standard libraries and it is needed to run Java programs;
- JDK includes JRE and development tools, it is needed to develop Java programs.