next up previous contents
Next: 2. Concepts of ION Up: YAON, a Static Diagram Technique Systems Previous: Introduction

  
1. Why Java?

In ``The Java Language Environment: A white Paper,''[GM96] Sun describes Java as follows:

Java: A simple, object-oriented, distributed, interpreted, robust, secure, architecture neutral, portable, high-performance, multithreaded, and dynamic language.

* Simple:
The simplicity of Java means that a programmer could learn it quickly. The number of language constructs has been kept small and it has a look and feel familiar to C, C++ and Objective-C. Therefore programmers can easily migrate to Java. Java does not support pointers which are a notorious source of bugs. Eliminating them simplifies the language and eliminates many potential bugs. Memory is automatically allocated and deallocation is done by the garbage collector and must not be explicitly programmed.

* Object-Oriented:
Java is an Object-Oriented language from the ground up. Java includes numbers, booleans and characters as ground types. In Java, Classes are not first class citizens, i.e. classes are not objects and therefore the metaclass concept is not supported. In this way, classes can be defined only statically. Java supports single inheritance but some aspects of multiple inheritance can be achieved using the interface concept. That is, multiple inheritance exists only for abstract methods and static-final variables (i.e. class constants).

* Distributed:
Java has been designed to support applications on networks. It supports different levels of connectivity through classes in the java.net package. The URL class allows a Java application to open and access remote objects on the internet. In Java, it is transparent if a file is local or remote. Using the Socket class, one can create distributed clients and servers. New upgrades of Java support Remote Method Invocation (RMI). Approaches which execute code on other machines across a network have been confusing as well as tedious to debug. The nicest way to think about them is that some objects happen to live in another machine, and then you can send a message to that object and get a result as if the object lived on your local machine. This simplification is exactly what Java Remote Method Invocation has implemented since version 1.1.

* Interpreted:
The Java compiler generates byte-code instead of machine-dependent code. To run a program one has to load it into the Java virtual machine. This machine has been implemented for the most popular operating systems.

* Robust:
A main source of errors in the C programming language is pointer manipulation. The explicit use of pointers has been removed from Java and in this way Java programs are easier to debug. On the other hand Java is a strongly typed language and therefore extensive compile-time checking for potential type errors is done. Java requires explicit method declarations and there are no implicit declarations (as in C, for example). The exception handling model of Java allows to group all the error handling code in one place via the try/catch/finally construct.

* Secure:
As already mentioned, Java has no pointers and therefore a program cannot get out of its program segment. Also the Java compiler does not handle memory layout decisions and one cannot write dynamic code. In other words one cannot evaluate a string which contains a piece of correct code. Java has neither pointers nor pointer arithmetic which could be used to sidestep Java's run-time checks and security mechanism. Another layer of security protection is commonly referred to as the ``sandbox model'': untrusted code is placed in a ``sandbox'' where it can play safely without doing any damage to the ``real world'' or full Java environment. When an applet or other untrusted code is running in the sandbox, there are a number of restrictions on what it can do. The most obvious of these restrictions is that it has no access whatsoever to the local file system. There are a number of other restrictions in the sandbox as well. These restrictions are enforced by a SecurityManager class. The model works because all of the core Java classes that perform sensitive operations, such as filesystem access, first ask permission of the currently installed SecurityManager. If the call is being made, directly or indirectly, by untrusted code, the security manager throws an exception, and the operation is not permitted. These things make Java ``secure'' or, at least, more secure than other programming languages. It is also worth mentioning that some security ``holes'' have been discovered in early versions of Java. These ``holes'' have been repaired in current versions. A chronology of security-related bugs is available. Also a Frequently Asked Questions file on Java Security is available. As one can expect, security is a very ``hot'' theme when implementing distributed systems in open networks.

* Architecture Neutral:
As Java programs are compiled to byte-code machine, compiled programs will run on every architecture which implements the Java virtual machine. In this way programmers do not need to maintain software versions for different platforms; they have only to maintain one version. The compiled version will run with the same look and feel, or at least similar, on any platform. It is assumed that any implementation of the Java virtual machine fulfils the intended semantics of the original one. This is not always the case. Moreover, different semantics for the scheduling have been detected under different implementations, specially those running under Windows 95 and Windows NT. It is expected in the near future, that any new version of the Java virtual machine behaves as expected. I.e. it is expected that Java behaves trully architecture neutral.

* Portable:
Following the point above, portability is achieved for free. There are no implementation dependent features. For example, Java explicitly defines the size of basic types and therefore a double has the same size in any platform. A pure Java program is one that relies only on the documented and specified Java platform. This sentence implies that Java programs are not trully portable. This is true; there are some aspects of Java (operating system calls, file names, paths to files, events, etc. for example) which are not portable to any platform. There is a critical distinction - and connection - between portability and purity. Most people think of a portable program as ``one that produces the same results on any platform''. This is actually a very unprecise definition.

We might be tempted to define a portable program as ``one that fulfills its function on any platform''. However, this definition is very hard to apply because the ``function'' of each program is specific to that program. Using this definition, we cannot evaluate the portability of a program without (ultimately) understanding the requirements of its users; this definition blurs the distinction between portability and quality.

However, we can determine a simple specification without understanding the requirements of the user: normal termination. The Java language defines two exit paths for any procedure: a normal termination, expressed as an exit or return, and an abrupt termination, expressed as a throw of an exception. Clearly, a program has failed to operate normally when the program as a whole terminates abruptly due to an uncaught exception.

For testing the portability and ``purity'' of a Java code, a 100% purity test has been implemented by SUN. This test is a program which gives some hints of which parts of the input code is not portable. Of course termination of programs cannot be evaluated.

* High-performance:
As Java is an interpreted language, one cannot expect the performance of a compiled one. Nevertheless, Java code is faster than other codes of interpreted languages in UNIX environments such as perl, tcl, etc. or script languages as bash, sh, csh, etc. Some experiments have been done comparing similar systems implemented in languages which compile to native code and Java. The result is not surprisingly: native code is faster than Java code in factors between 100 and 1000. New technologies are under development such as ``Just in Time Compiling'' (JITC). JITC takes Java compiled classes (byte code machine) and generates native code for that platform. It is expected that the generated native code will run as fast as native code generated by other compilers. Statistics about this point are still missing.

* Multithreaded:
Java has built-in constructs for multithreading. These primitives are based on the monitor and condition variable model. Using the synchronized keyword, one can specify that certain methods within a class cannot run concurrently. Java makes programming with threads much easier by providing built-in language support for threads. The java.lang package provides a Thread class that supports methods to start and stop threads and set thread priorities, among other things.

* Dynamic:
Java manipulates memory in a dynamic way. Classes are loaded by demand even across a network. The distributed nature of Java really shines when combined with its dynamic class loading capabilities. Together, these features make it possible for a Java interpreter to download and run code from across a network.

We can summarize that Java is not perfect, but compared to other popular programming languages one can conclude that all the features make Java a programming language with aptitudes to implement software engineering projects and distributed systems. Moreover, for a short time ISO members have approved SUN'S pas application. I.e. Java is not more a de facto standard but also a ISO standard. It is expected that in the mean future to have implementations of the Java virtual machine compliant with the standard.