Features of Java:
Dynamic, Complied and Interpreted
my previous post, we have seen how java is so flexible and simple, while very
small and yet equipped with powerful features like Object Oriented principles
(OOPS). Now in this post we examine one of the important features of java i.e.
how java is compiled and interpreted.
lies the major difference between Java and languages such as C++, Pascal, and
many others. These languages compile their source program into object code (an
.obj file). The linker converts the generated object code into an executable
(.exe file) by combining object code with the desired libraries. When we run
the EXE, the loader in the operating system loads the executable code in memory,
resolves the function references with the absolute memory addresses, and
executes the code. Compiling and running a Java program differs substantially from
the preceding procedure. As explained earlier, a Java compiler translates the
Java source program into what is known as bytecode, which is the set of
instructions for a virtual CPU. No linker process is involved when we create an
executable from a Java source program. In fact, the only executable that is created
from a Java source program is the bytecode. So how does this bytecode run on a
real CPU? When we run a Java executable (bytecode) on our machine, an
interpreter converts each bytecode instruction into a real CPU instruction.
This instruction then executes on the real CPU, so compiling and running a Java
program involves both compilation and interpretation processes. Thus, Java is considered
both compiled and interpreted.
Java bytecode is interpreted into machine language instructions at runtime, Java
code execution suffers in performance. To overcome this performance limitation,
most JVMs implement a number of code optimization techniques, one of which is
the use of a Just-in-Time (JIT) compiler that translates the bytecode into
machine language code before the real CPU begins the program execution.
Obviously, the JIT compiler cannot perform as many optimizations as an offline
compiler such as the C++ compiler, because it has to translate the bytecode
into machine language code in real time. If the JIT compiler were to attempt to
do so, it would take a long time to start the program after the user fires it
up from the command line. We have to consider the trade-off between start-up time
and throughput. VMs employ a variety of optimization techniques these days.
Most of them can be tuned to prefer start-up over throughput, or how quickly
they adapt the optimizations. There’s a whole body of expertise on tuning VMs
for performance, and for many applications, the Java version is as quick as
(and sometimes quicker than) the C++ counterpart.
important feature introduced in Java is its dynamic nature. As we have seen, a
Java source program compiles into bytecode. This bytecode is stored in a file
with the extension .class.
running Java application can load a compile-time unknown .class file,
understand the defined class, instantiate it, and use it for its own purpose.
This process is called “introspection and reflection” in Java.
A running Java program can introspect an unknown class, understand the attributes
and operations defined in it, create an instance of the class, set the
attributes of the created object, and invoke the member functions on the
created object. It can also create an array of objects of this unknown type at
runtime. This is the dynamic nature of Java.