If you work with java you know the JVM. But do you know how it works? Let’s see an overview of what happens behind the scenes.
What is JVM
The Virtual Machine has the idea to implements a physical machine, and Java use that to make possible execute the programs in any platform (WORA – Write Once Run Anywhere).
Java Virtual Machine can be defined such an environment where you can execute your Java application in any platform. It provides, for example, dynamic memory management, garbage collector, Threads, IO and native operations. The main tasks in the JVM are loading code, verifying code, executing code and provide a runtime environment.
The JRE (Java Runtime Environment) is the JVM’s implementation. The JDK is a software development environment to implement java applet and apps. It includes, for example, JRE (loader/interpreter), a compiler (javac), a document generator (Javadoc) and an archiver (jar).
More detail about the differences between JVM, JRE and JDK you can see here.
It is responsible for loading, linking (verify [bytecode], prepare [memory allocation to static variables], resolve [references]) and initialization (static variables and blocks) the class files when it is referred by other class at runtime.
Runtime Data Areas
It is composed by Method Area (class level data – static blocks/static variables/references), Heap Area (objects, instances and arrays), Stack Area (a new stack is created for each new thread; local variables are created in the stack; one stack frame is created for every method call), PC Registers (a new register is created for each thread to hold address’s instructions), Native Method Stacks (native methods informations – by each thread).
It reads and executes the bytecode assigned from the Runtime Data Area piece by piece. Interpreter (interpreter [fast] and execute[slowly] the bytecode), JIT Compiler (it is used to repeated code which compiles entire bytecode and changes it to native code, used directly for repeated method calls – it is responsible for the optimization of the Java programs ), Garbage Collector (collects and removes unreferenced objects).
Java Native Interface (JNI)
It is like an interface between the Java code and the native (C/C++). It provides the native libraries required for the Execution Engine.
Native Method Libraries
Collection of Native libraries (related to the platform) and native methods implementation used by Execution Engine.
The heap memory is where are allocated instances. Until Java 7 the memory is divided into generations based on the age of the objects. The Young generation is the part of memory where are the small objects and which are collected frequently. The Old Generation has a larger object and promoted from the Young part. The Permanent Generation (PermGen), store class-level information (fields, methods, runtime constant pool, internalized Strings, etc). The data is rarely collected. Before Java 7 the interned Strings were stored in the PermGen.
The JVM is responsible for memory management, allocating and de-allocating memory. This management is performed by the Garbage Collector (GC) which verify if the objects are referenced or not. If the object is used it must be kept in the heap. The rest of the objects will be removed and the heap space will be reorganized to have the alive objects together in a continuous position.
Since Java 8 the PermGen does not exist anymore and it has been replaced by the Metaspace which not contiguous in heap. Now the metadata was moved to the native memory and it makes possible to be free of the PermGen exception (no more java.lang.OutOfMemoryError). You can control the limit using MaxMetaspaceSize.
- Run your code faster and more efficiently
- Interoperate directly with most modern programming languages
- Embed languages with the Graal SDK
- Create compiled native images
- Use a single set of tools to monitor, debug, and profile all your code
- The JVM Architecture Explained
- How JVM works
- Difference Between JVM, JRE and JDK