Java Lesson 2 - Aspects of Java Environment
We are going to discuss the aspects of the Java environment in this tutorial, such as
- Java compiler
- Bytecode
- JVM
- JDK, JRE
Before learning about what is under the hood of Java, let's have a look at what we have done up to now. In the previous lesson, we created our first Java program, Main.java, which print "Hello Java" to our command prompt (Terminal).
- First we created our Java code and saved it as Main.java.
- Then we compiled it using
javaccommand. - Lastly, we executed our program using
javacommand.
Those were the simple steps that we carried out to execute our Java program. But when executing our Java program, there is a lot happening under the hood. Here is what happen when a Java program executing.
Java Execution Flow
1. What is Java Compiler?
In programming generally, a compiler is a computer program that converts computer code written in a programming language to machine code. Whenever a human writes a computer code, it is only readable by humans so that, to make it readable on our computers, we need to convert it into machine code. Machine code contains the lowest level of instruction that only computers can read. These are almost impossible for humans to read and understand. But the Java compiler acts differently. It converts Java codes that we write into a Bytecode. Therefore Java compiler takes the Main.java file and generates a Bytecode called Main.class.
2. What is a Bytecode?
Java Bytecode contains instructions for the Java Virtual Machine (which we will discuss in the next topic). Bytecode is not a complete machine code. Therefore computers cannot directly understand or execute any of the instructions inside a Bytecode, only JVM (Java Virtual Machine) can read them and convert them to machine instructions. We remember that Java is a Platform Independent language. Bytecode is the reason why it is possible. Whenever we install Java on an operating system (Windows, macOS, Linux), the corresponding JVM also installed. JVM knows how to convert instructions in Bytecode into platform-specific machine instructions. Therefore you write Java codes only once and compile them once. We can use the Bytecode that we generated in any platform without stressing about platform differences.
3. What is JVM?
Java Virtual Machine is the Virtual Machine that runs the Java Bytecodes. It is a specification that provides a runtime environment in which Java Bytecodes can be executed. JVM is platform-dependent. Therefore we need a particular implementation of JVM for a specific platform. For example, JVM for Windows is designed to convert Bytecode instructions to Windows-specific machine instructions. This platform-dependent JVM makes Java codes be able to write once and run everywhere. JVM delivers optimal performance for Java applications using many advanced techniques such as Memory Model, Garbage Collector, and Adaptive Optimizer. JVM performs following operations:
- Load codes
- Verify codes
- Execute codes
- Provide runtime environment
- Memory Area
- Class file format
- Register set
- Garbage-collected heap
- Fatal error reporting, etc
4. JVM Architecture
Class Loader is a JVM subsystem used for loading class files. It performs the following three functions,
1. Loading
- JVM has three types of class loaders to load classes. They are Bootstrap, Extension, and Application Class Loader.
- Bootstrap Class Loader: It loads the rt.jar file that contains all class files of Java Standard Edition such as java.lang package classes, java.net package classes, java.util package classes, java.io package classes, java.sql package classes, etc.
- Extension Class Loader: This is the child class loader of Bootstrap Class Loader and parent class loader of Application Class Loader. It loads the jar files located inside $JAVA_HOME/jre/lib/ext directory.
- Application Class Loader: This is the child class loader of Extension Class Loader. It loads the class files from classpath. By default, the classpath is set to the current directory.
- Unless the class is found by the class loader, ClassNotFoundException is thrown.
Once the classes are loaded, linking is performed. A Bytecode verifier will verify whether the generated bytecode is correct or not. Linking also performs memory allocation for static variables and methods inside the class.
3. Initialization
This is the final phase of class loading. All static variables will be assigned with their original values and static blocks will be executed in this phase.
4.2. JVM Memory Areas
JVM divides its memory into multiple parts to store specific pieces of Java application data.
- Method Area: stores class structures like metadata, the constant runtime pool, and the code for methods.
- Heap: stores all objects that are created during application execution.
- JVM Language Stack: store local variables, and intermediate results. All such variables are local to the thread by which they are created. Each thread has its own JVM stack, created simultaneously as the thread is created. So all such local variable are called thread-local variables.
- PC Registers: store the physical memory address of the statements which is currently executing. In Java, each thread has its separate PC register.
- Native Method Stack: Java supports and uses native code as well. Native method stacks hold the instruction of native code.
4.3. JVM Execution Engine
The Execution Engine is designated to execute all the Bytecodes assigned to JVM. It reads Bytecode and executes one by one. Execution Engine uses two inbuilt interpreter and JIT Compiler to convert the Bytecode to machine code and execute it.
4.3.1. Interpreter
JVM Interpreter converts each Bytecode instruction to corresponding native instruction by looking a predefined JVM-Instructions to Native Instruction mapping. The Interpreter directly executes instructions without performing any optimizations.
4.3.2. JIT Compiler
JIT Compiler interacts with JVM at runtime and compiles appropriate Bytecode sequence to machine code to improve performance. Typically JIT Compiler takes a block of code and optimizes it. Then translate it into optimized machine code (Not one statement at a time like the Interpreter).
4.4. What is JRE?
The Java Runtime Environment is a software package that bundles jar libraries, Java Virtual Machine (JVM), and other components to run applications written in Java. To execute any Java application, we need JRE installed on our computer. JVM is a part of JRE distributions. JRE bundles the following components:
- DLL files used by the JVM
- Code libraries, property settings, and resource files used by the Java runtime environment (rt.jar, charsets.jar, etc)
- Java extension files such as localedata.jar.
- Contains files used for security management. These include the security policy (java.policy) and security properties (java.security) files.
- Jar files containing support classes for applets.
- Contains TrueType font files for use by the platform.
4.5. What is JDK?
JDK is a superset of JRE. JDK contains everything that JRE has along with development tools for developing, debugging, and monitoring Java applications. We need JDK when we need to develop Java applications.
JRE vs. JDK





Comments
Post a Comment