Java
Java has become a major factor in computing. Java is interesting in
that it's a software, not hardware, extension. Java defines a Java "Virtual
Machine" as a software CPU that executes Java instructions. This machine
is platform independent and can run on many different CPUs. Java defines
its own software ISA.
Java's advantages were not in speed. It is defined as a byte-coded interpretive
language. Java instructions are individually decoded and interpreted, which
can make for slower executions on the order of 20 to 40 times slower than
C or C++ code.
Java does have its advantages though. For one thing, it's a newer language,
one designed for multimedia and GUI operations. For another, it's a subset/superset
of C/C++. Among other things, Java does not support pointers. Pointers
were the glory of C, enabling programmers great flexibility. They were
also its bane; problems with pointers trouble many developers. Java takes
a much more disciplined approach to pointers: they are called "references"
and are either null or point to an actual object; no dangling pointers,
no de-referencing pointers (to cause an exception). Java also fixes a number
C/C++ problems: array indexing is checked (out-of-bounds index equaling
an exception) and fields have defined initial values.
In many ways, Java is a smaller, simpler and better C and C++. Unlike
C and C++, it defines a runtime or "Virtual Machine" that contains
many of the functions routinely compiled into C programs. With Java, they
are part of the virtual machine. Additionally, Java forgoes traditional
memory management: it supports automatic memory management and garbage
collection.
The traditional Java implementation model is to compile Java source
into .class files containing machine-independent bye-code instructions.
These .class files are downloaded and interpreted by a browser
or a Java "Virtual Machine." Figure
8 shows the typical JAVA implementation.

Figure 8: Typical Java implementation
Interpreting Java byte-codes makes Java code many times slower than
comparable C or C++ programs. One approach to improving this situation
is "Just-In-Time" (JIT) compilers. These dynamically translate
byte-codes into machine code just before a method is first executed.
This is a major advance over slower interpretation, but has the drawback
that the JIT compilation must be done each time the application executes.
Moreover, since the JIT compiler must make use of run-time resources to
compile, it cannot devote much time to serious optimizations. Compilers
can because they use host development resources, not runtime resources.
Additionally, JIT compilers need memory resources to run; this can be very
wasteful for embedded systems that try to minimize memory costs. No JIT
compiler today fits in less than 512 KB of local memory. That's wasteful
for many memory critical embedded applications.
Compiled Java
Compiling Java eliminates many common Java problems, especially for
speed of execution. Compiled Java will be platform specific; however, many
programmers are more interested in Java as a modern language, extending
clean C/C++ program output. Although Java is, still, without platform independent
execution, especially with its large interpreter performance penalty, a
compiled Java still defines a Java virtual machine. However, code developed
for that machine is compiled on the host, converting Java source code to
platform-specific runtime code. The Java runtime, which provides features
such as garbage collection, and exception handling, is still needed. However,
for many embedded applications, it is possible to dispense with the need
for a full blown Java VM or JIT compiler.
Cygnus Solutions is working on a Java programming environment that uses
a conventional compiler, linker and debugger. These are enhanced versions
of the existing GNUPro C/C++ development tools that have been ported to
most development systems for just about every microprocessor and micro-controller
in use. With the GNUPro Java compiler, Java byte-codes (or source) will
be portable to a wide range of development platforms and targets. Such
an approach to implementing Java is also expected to deliver very high
performance. See Figure 9 for an example of
compiled Java.
The core of Cygnus Solutions' compiled Java is the jcl compiler,
a new GCC front-end. This is similar to other GNU front-ends such as cc1plus
for C++, and shares most of the front-end code. This new compiler, jcl,
is unique in that it can read-in and compile either Java source files or
Java byte-codes. Future versions will use an integrated parser that handles
both source code and byte-codes. Even with source code operation, it's
important to be able to handle byte-codes to support Java code from other
tools and to use Java byte-code libraries.
The basic strategy for translating Java stack-oriented byte-code operations
is to convert Java's stack-oriented operations into operations on variables.
jcl creates a dummy local variable for each Java stack slot or
local variable. These are mapped into GCC "virtual registers"
and, then, into standard GCC register allocation assigns each "virtual
register" to a hard register or to a C/C++ stack location.
The jcl program creates standard assembler files that are processed
by the standard unmodified GNU assembler. The resulting object files can
go into a dynamic or static library, or they can be linked together with
the runtime into an executable. The standard linker needs to be able to
support static initializers, but it already does that for C++.
A compiled Java program still needs a Java run-time environment, just
as C++ or Ada requires its own run-time. Java, however, requires more run-time
support than these mainstream languages. It needs support for threads,
garbage collection, type reflection and all the primitive Java methods,
as well as being able to dynamically load new Java byte-coded classes.
This last feature may not be a requirement in some embedded applications
that use fixed code. Cygnus Solutions is integrating Kaffe, a version of
the Java run-time or Java Virtual Machine, with its Java compiler. Kaffe
was developed by Tim Wilkinson who made it publicly available on the Internet.
A major factor in Java's success in becoming a mainstream programming
language is having mainstream implementation techniques (specifically,
an optimizing, ahead-of-time compiler that allows much better optimization
along with much faster application start-up times than with JIT translators).
Cygnus Solutions is writing a Java front-end for the GNU compiler, GCC,
in order to translate Java bytecodes to machine code. This will take advantage
of a widely used, proven technology in order to solve many future needs.
See Figure 9 to see how Java works.

Figure 9: Compiled Java
|