The Java Virtual Machine
The Java Virtual Machine Specification defines the JVM as:
An imaginary machine that is implemented by emulating it in software on a real machine. Code for the JVM is stored in .class files, each of which contains code for at most one public class.
The Java Virtual Machine Specification provides the hardware platform specifications to which you compile all Java technology code. This specification enables the Java software to be platform-independent because the compilation is done for a generic machine, known as the JVM. You can emulate this generic machine in software to run on various existing computer systems or implement it in hardware.
The compiler takes the Java application source code and generates bytecodes. Bytecodes are machine code instructions for the JVM. Every Java technology interpreter, regardless of whether it is a Java technology development tool or a web browser that can run applets, has an implementation of the JVM.
The JVM specification provides concrete definitions for the implementation of the following: an instruction set (equivalent to that of a central processing unit [CPU]), a register set, the class file format, a runtime stack, a garbage-collected heap, a memory area, fatal error reporting mechanism, and high-precision timing support.
The code format of the JVM machine consists of compact and efficient bytecodes. Programs represented by JVM bytecodes must maintain proper type discipline. The majority of type checking is done at compile time.
Any compliant Java technology interpreter must be able to run any program with class files that conform to the class file format specified in The Java Virtual Machine Specification.
The JVM design enables the creation of implementations for multiple operating environments. For example, Sun Microsystems provides implementations of the JVM for the Solaris OS and the Linux and Microsoft Windows operating environments.
Many programming languages permit the memory to be allocated dynamically at runtime. The process of allocating memory varies based on the syntax of the language, but always involves returning a pointer to the starting address of a memory block.
After the allocated memory is no longer required (the pointer that references the memory has gone out of extent), the program or runtime environment should de-allocate the memory.
In C, C++, and other languages, you are responsible for de-allocating the memory. This can be a difficult exercise at times, because you do not always know in advance when memory should be released. Programs that do not de-allocate memory can crash eventually when there is no memory left on the system to allocate. These programs are said to have memory leaks.
The Java programming language removes you from the responsibility of de-allocating memory. It provides a system-level thread that tracks each memory allocation. During idle cycles in the JVM, the garbage collection thread checks for and frees any memory that can be freed.
Garbage collection happens automatically during the lifetime of a Java technology program, eliminating the need to deallocate memory and avoiding memory leaks. However, garbage collection schemes can vary dramatically across jvm implentations.