The execution engine executes bytecode in runtime data areas. It executes bytecode by each line and uses the information available in runtime data areas. The execution engine can be classified into three parts:
Interpreter: This reads, interprets, and executes bytecode by each line. It interprets and executes bytecode quickly; however, it can be very slow in executing interpreted results.
Just-In-Time (JIT): In order to overcome the interpreter's slowness in executing interpreted results, the JIT compiler converts the bytecode to native code once the interpreter interprets the code the first time. Execution happens fast with native code; it executes instructions one by one.
Garbage collector: This destroys anything that is not referenced. This is very important, so anything not required will be destroyed to create room for new execution.