Looking for Java resources? Check out the Java
Coffee Break directory!
Inside Java :
The Java Programming Language
By David Reilly
Inside Java offers a glimpse behind the Java platform, and related
technologies. In this month's column, I'll show you an overview of the
Java programming language.
Java - an island of Indonesia, a
type of coffee, and a
programming language. Three very different meanings, each in
of importance. Most programmers, though, are interested in the Java
programming language. In just a few short years (since late 1995), Java has taken the
software community by storm. Its phenomenal success has made Java the
fastest growing programming language ever. There's plenty of hype about
Java, and what it can do. Many programmers, and end-users, are confused
about exactly what it is, and what Java offers.
Java is a revolutionary language
The properties that make Java so attractive are present
in other programming languages. Many languages are ideally suited for
certain types of applications, even more so than Java. But Java brings
all these properties together, in one language. This is a revolutionary
jump forward for the software industry.
Let's look at some of the properties in more detail: -
automatic garbage collection
network and "Internet" aware
simplicity and ease-of-use
Many older languages, like C and Pascal, were procedural
languages. Procedures (also called functions) were blocks of code that
were part of a module or application. Procedures passed parameters
(primitive data types like integers, characters, strings, and floating
point numbers). Code was treated separately to data. You had to pass
around data structures, and procedures could easily modify their
contents. This was a source of problems, as parts of a program could
have unforeseen effects in other parts. Tracking down which procedure
was at fault wasted a great deal of time and effort, particularly with
In some procedural language, you could even obtain the
memory location of a data structure. Armed with this location, you could
read and write to the data at a later time, or accidentally overwrite
Java is an object-oriented language. An
object-oriented language deals with objects. Objects contain
both data (member variables) and code (methods). Each object belongs to
a particular class, which is a blueprint describing the member
variables and methods an object offers. In Java, almost every variable
is an object of some type or another - even strings. Object-oriented
programming requires a different way of thinking, but is a better way to
design software than procedural programming.
There are many popular object-oriented languages
available today. Some like Smalltalk and Java are designed from the
beginning to be object-oriented. Others, like C++, are partially object-oriented, and partially procedural. In C++, you can still
overwrite the contents of data structures and objects, causing the
application to crash. Thankfully, Java prohibits direct access to memory
contents, leading to a more robust system.
Most programming languages are designed for a specific
operating system and processor architecture. When source code (the
instructions that make up a program) are compiled, it is converted to machine
code which can be executed only on one type of machine. This process
produces native code, which is extremely fast.
Another type of language is one that is interpreted.
Interpreted code is read by a software application (the interpreter),
which performs the specified actions. Interpreted code often doesn't
need to be compiled - it is translated as it is run. For this reason,
interpreted code is quite slow, but often portable across different
operating systems and processor architectures.
Java takes the best of both techniques. Java code is
compiled into a platform-neutral machine code, which is called Java bytecode.
A special type of interpreter, known as a Java Virtual Machine (JVM), reads the
bytecode, and processes it. Figure One shows a disassembly of a small Java
application. The bytecode, indicated by the arrow, is represented in text
form here, but when compiled it is represented as bytes to conserve
Figure One - Bytecode disassembly for "HelloWorld"
The approach Java takes offers some big advantages over
other interpreted languages. Firstly, the source code is protected from
view and modification - only the bytecode needs to be made available to
users. Secondly, security mechanisms can scan bytecode for signs of
modification or harmful code, complimenting the other security
mechanisms of Java. Most of all though, it means that Java code can be
compiled once, and run on any machine and operating system combination
that supports a Java Virtual Machine (JVM). Java can run on Unix,
Windows, Macintosh, and even the Palm Pilot. Java can even run inside a
web browser, or a web server. Being portable means that the application
only has to be written once - and can then execute on a wider range of
machines. This saves a lot of time, and money.
If you've ever written complex applications in C, or
PERL, you'll probably have come across the concept of multiple processes
before. An application can split itself into separate copies, which run
concurrently. Each copy replicates code and data, resulting in increased
memory consumption. Getting the copies to talk together can be complex,
and frustrating. Creating each process involves a call to the operating
system, which consumes extra CPU time as well.
A better model is to use multiple threads of execution,
referred to as threads for short. Threads can share data and
code, making it easier to share data between thread instances. They also
use less memory and CPU overhead. Some languages, like C++, have support
for threads, but they are complex to use. Java has support for multiple
threads of execution built right into the language. Threads require a
different way of thinking, but can be understood very quickly. Thread
support in Java is very simple to use, and the use of threads in
applications and applets is quite commonplace.
Automatic garbage collection
No, we're not talking about taking out the trash (though
a computer that could literally do that would be kind of neat). The term
garbage collection refers to the reclamation of unused memory space.
When applications create objects, the JVM allocates memory space for
their storage. When the object is no longer needed (no reference to the
object exists), the memory space can be reclaimed for later use.
Languages like C++ force programmers to allocate and
deallocate memory for data and objects manually. This adds extra
complexity, but also causes another problem - memory leaks. When
programmers forget to deallocate memory, the amount of free memory
available is decreased. Programs that frequently create and destroy
objects may eventually find that there is no memory left. In Java, the
programmer is free from such worries, as the JVM will perform automatic
garbage collection of objects.
Security is a big issue with Java. Since Java applets
are downloaded remotely, and executed in a browser, security is of great
concern. We wouldn't want applets reading our personal documents,
deleting files, or causing mischief. At the API level, there are strong
security restrictions on file and network access for applets, as well as
support for digital signatures to verify the integrity of downloaded
code. At the bytecode level, checks are made for obvious hacks, such as
stack manipulation or invalid bytecode. The strong security mechanisms
in Java help to protect against inadvertent or intentional security
violations, but it is important to remember that no system is perfect.
The weakest link in the chain is the Java Virtual Machine on which it is
run - a JVM with known security weaknesses can be prone to attack. It is
also worth noting that while there have been a few identified weaknesses
in JVMs, they are rare, and usually fixed quickly.
Network and "Internet" aware
Java was designed to be "Internet" aware, and
to support network programming. The Java API provides extensive network
support, from sockets and IP addresses, to URLs and HTTP. It's extremely
easy to write network applications in Java, and the code is completely
portable between platforms. In languages like C/C++, the networking code
must be re-written for different operating systems, and is usually more
complex. The networking support of Java saves a lot of
time, and effort.
Java also includes support for more exotic network
programming, such as remote-method invocation (RMI), CORBA and Jini.
These distributed systems technologies make Java an attractive choice
for large distributed systems.
Simplicity and ease-of-use
Java draws its roots from the C++ language. C++ is
widely used, and very popular. Yet it is regarded as a complex language,
with features like multiple-inheritance, templates and pointers that are
counter-productive. Java, on the other hand, is closer to a
"pure" object-oriented language. Access to memory pointers is
removed, and object-references are used instead. Support for multiple-inheritance
has been removed, which lends itself to clearer and simpler class
designs. The I/O and network library is very easy to use, and the Java
API provides developers with lots of time-saving code (such as
networking and data-structures). After using Java for awhile, most
developers are reluctant to return to other languages, because of the
simplicity and elegance of Java.
Java provides developers with many advantages. While
most of these are present in other languages, Java combines all of these
together into one language. The rapid growth of Java has been nothing
short of phenomenal, and shows no signs (yet!) of slowing down. In next
month's column, I'll talk more about the heart of Java - the Java