JDK in Java
Three Java development software packages are available, but the JDK is the most complete. It has everything Java programmers need to write, compile, and debug programs. The JDK’s architecture relies on the JRE and JVM. Installing the JDK fully supports Java application development and functioning due to its integrated structure.
The JDK offers a suite of essential development tools. Foremost among these is the javac
command, which is the Java compiler. It translates .java
code files, written by the programmer, into .class
bytecode files that the JVM can execute. Other vital tools within the JDK include jar
and jarsigner
for creating and managing Java Archive (JAR) files, which are used to package Java applications. Debugging and monitoring tools like jconsole
, jstat
, jinfo
, and jps
are also provided, aiding developers in optimising and troubleshooting their applications.
The JDK typically also includes the code for Java’s standard libraries, which can be invaluable for understanding how the platform’s core functionalities operate. JDK, introduced significant enhancements to the Java language, such as lambda expressions, which profoundly impacted how Java code is written.
Java Virtual Machine (JVM)
Your computer’s RAM houses the Java Virtual Machine (JVM). Our platform-independent execution environment interprets Java bytecode into native machine code for the hardware and operating system. Running any Java program requires the JVM to interpret and execute bytecode.
The JVM underpins Java’s “Write Once, Run Anywhere” (WORA) philosophy. When compiled, Java code doesn’t become Windows or macOS-specific machine code. A universal intermediate representation called bytecode is produced instead. Java virtual machines (JVMs) for each platform load, verify, and execute this bytecode. Java programs are portable between computing environments without recompilation thanks to this abstraction.
Class Loader loads .class
files into memory; Bytecode Verifier checks bytecode for Java’s security and structural rules; and Execution Engine converts bytecode into executable machine code. Runtime Just-In-Time (JIT) compilation of frequently executed bytecode chunks into native machine code is a key feature of the Execution Engine. Java applications run quicker with this optimisation than with bytecode interpretation. JVM understands bytecode, however if written into a native format, the program would lose portability yet run without the virtual machine.
Java Runtime Environment (JRE)
Running Java applications requires the Java Runtime Environment (JRE), which offers pre-defined .class
files (library files) and other resources. Most importantly, the JRE contains the JVM. Just install the JRE if you only need to run Java apps, not build them.
The JRE bundles the core libraries and tools required to launch and manage Java applications. These tools include the java
command, which is used to invoke the JVM and start a Java application. Other utilities, such as jjs
(for the Nashorn JavaScript engine), keytool
(for manipulating keystores), and policytool
(for editing security policies), are also part of a typical JRE.
Furthermore, JRE installers from Java 7 Update 6 onwards have incorporated JavaFX. The JRE’s purpose is to provide a complete and consistent environment for the compiled Java bytecode, ensuring that applications can run reliably without the developer needing to worry about underlying platform specifics.
Differences and Relationship
The JDK encompasses the JRE, which encompasses the JVM.
- Platform-independent Java bytecode is executed by the JVM.
- The JRE runs Java apps. JVM, standard libraries, and Java program resources are included.
- The JDK includes the javac compiler, debugging utilities, and the entire JRE (and JVM) for Java programming.
When running existing Java applications, the JRE is enough. Since it includes the whole development toolchain and runtime features, the JDK is necessary for writing, compiling, and debugging Java applications. Whether started by the JRE or JDK, the JVM executes Java bytecode.
Code Example: The “Hello World!” Lifecycle
To illustrate this relationship, let’s examine the lifecycle of a simple “Hello World!” program:
Code:
// MyFirstJavaProgram.java
public class MyFirstJavaProgram {
/* This is my first java program.
* This will print 'Hello, World!' as the output
*/
public static void main(String[] args) {
System.out.println("Hello, World!"); // prints Hello, World!
}
}
Explanation of Lifecycle:
- Writing the Code: A developer writes “Hello, World!” Java code first. Human-readable code is usually written in a text editor or IDE like NetBeans or Eclipse and saved as
MyFirstJavaProgram.java
. - Compiling with JDK: The developer compiles the code using the JDK’s essential
javac
compiler. Javac
generatesMyFirstJavaProgram.class
if compilation succeeds. Contains JVM-specific bytecode, making it platform-independent.- Running with JRE/JVM: Finally, the developer runs the compiled application by invoking the JRE’s
java
interpreter. - The JVM loads
MyFirstJavaProgram.class
with this command. It next verifies the bytecode for security and integrity and converts it into native machine code the computer’s processor can run. It runs on any machine with a suitable JRE.
Code Output:
Hello, World!
Java’s built-in output stream allows System.out.println()
to emit “Hello, World!” to the console. JDK, JRE, and JVM work together to offer Java’s promise of robust, portable applications throughout this process.
Java’s enduring popularity and widespread use stem from its core design philosophy, particularly its ability to execute programs across diverse platforms. This fundamental capability is realised through the interplay of three key components: the Java Virtual Machine (JVM), the Java Runtime Environment (JRE), and the Java Development Kit (JDK). Understanding the distinctions and relationships between these components is crucial for any Java developer.