Java ScreenShot
     

Screenshot Core Java 2: Volume I - Fundamentals

Table of Contents
 1.  An Introduction to Java


Java "White Paper" Buzzwords

The authors of Java have written an influential White Paper that explains their design goals and accomplishments. Their paper is organized along the following eleven buzzwords:

Simple

Portable

Object Oriented

Interpreted

Distributed

High Performance

Robust

Multithreaded

Secure

Dynamic

Architecture Neutral

 
We touched on some of these points in the last section. In this section, we will:
  • Summarize via excerpts from the White Paper what the Java designers say about each buzzword, and
  • Tell you what we think of that particular buzzword, based on our experiences with the current version of Java.
Java graphics notes_icon.gif

As we write this, the White Paper can be found at http://java.oracle.com/doc/language_environment.

Simple

We wanted to build a system that could be programmed easily without a lot of esoteric training and which leveraged today's standard practice. So even though we found that C++ was unsuitable, we designed Java as closely to C++ as possible in order to make the system more comprehensible. Java omits many rarely used, poorly understood, confusing features of C++ that, in our experience, bring more grief than benefit.

The syntax for Java is, indeed, a cleaned-up version of the syntax for C++. There is no need for header files, pointer arithmetic (or even a pointer syntax), structures, unions, operator overloading, virtual base classes, and so on. (See the C++ notes interspersed throughout the text for more on the differences between Java and C++.) The designers did not, however, attempt to fix all of the clumsy features of C++. For example, the syntax of the switch statement is unchanged in Java. If you know C++, you will find the transition to the Java syntax easy. If you are used to a visual coding environment (such as Visual Basic), you will not find Java simple. There is much strange syntax (though it does not take long to get the hang of it). More importantly, you must do a lot more coding in Java. The beauty of Visual Basic is that its visual design environment provides a lot of the infrastructure for an app almost automatically. The equivalent functionality must be programmed manually, usually with a fair bit of code, in Java. There are, however, third-party development environments that provide "drag-and-drop" style program development.

Another aspect of being simple is being small. One of the goals of Java is to enable the construction of software that can run stand-alone in small machines. The size of the basic interpreter and class support is about 40K bytes; adding the basic standard libraries and thread support (essentially a self-contained microkernel) adds an additional 175K.

This is a great achievement. Note, however, that the graphical user interface (GUI) libraries are significantly larger.

Object Oriented

Simply stated, object-oriented design is a technique for coding that focuses on the data (= objects) and on the interfaces to that object. To make an analogy with carpentry, an "object-oriented" carpenter would be mostly concerned with the chair he was building, and secondarily with the tools used to make it; a "non-object-oriented" carpenter would think primarily of his tools. The object-oriented facilities of Java are essentially those of C++.

Object orientation has proven its worth in the last 30 years, and it is inconceivable that a modern coding language would not use it. Indeed, the object-oriented features of Java are comparable to C++. The major difference between Java and C++ lies in multiple inheritance, for which Java has found a better solution, and in the Java metaclass model. The reflection mechanism (see ) and object serialization feature (see ) make it much easier to implement persistent objects and GUI builders that can integrate off-the-shelf components.

Java graphics notes_icon.gif

If you do not have any experience with object-oriented coding languages, you will want to carefully read s 4 through 6. These chapters explain what object-oriented coding is and why it is more useful for coding sophisticated projects than traditional, procedure-oriented languages like C or Basic.

Distributed

Java has an extensive library of routines for coping with TCP/IP protocols like HTTP and FTP. Java apps can open and access objects across the Net via URLs with the same ease as when accessing a local file system.

We have found the networking capabilities of Java to be both strong and easy to use. Anyone who has tried to do Internet coding using another language will revel in how simple Java makes onerous tasks like opening a socket connection. An elegant mechanism, called servlets, makes server-side processing in Java extremely efficient. Many popular web servers support servlets. (We will cover networking in Core Java 2, Volume II–Advanced Features of this tutorial.) The remote method invocation mechanism enables communication between distributed objects (also covered in Volume 2).

Robust

Java is intended for writing programs that must be reliable in a variety of ways. Java puts a lot of emphasis on early checking for possible problems, later dynamic (run-time) checking, and eliminating situations that are error-prone. . . . The single biggest difference between Java and C/C++ is that Java has a pointer model that eliminates the possibility of overwriting memory and corrupting data.

This feature is also very useful. The Java compiler detects many problems that, in other languages, would show up only at run time. As for the second point, anyone who has spent hours chasing memory corruption caused by a pointer bug will be very happy with this feature of Java. If you are coming from a language like Visual Basic or Cobol that doesn't explicitly use pointers, you are probably wondering why this is so important. C programmers are not so lucky. They need pointers to access strings, arrays, objects, even files. In Visual Basic, you do not use pointers for any of these entities, nor do you need to worry about memory allocation for them. On the other hand, there are many data structures that are difficult to implement in a pointerless language. Java gives you the best of both worlds. You do not need pointers for everyday constructs like strings and arrays. You have the power of pointers if you need it, for example, for linked lists. And you always have complete safety, since you can never access a bad pointer, make memory allocation errors, or have to protect against memory leaking away.

Secure

Java is intended to be used in networked/distributed environments. Toward that end, a lot of emphasis has been placed on security. Java enables the construction of virus-free, tamper-free systems.

In the first version of Core Java we said: "Well, one should 'never say never again,'" and we turned out to be right. A group of security experts at Princeton University found the first bugs in the security features of Java 1.0—not long after the first version of the Java Development Kit was shipped. Moreover, they and various other people have continued to find other bugs in the security mechanisms of all subsequent versions of Java. For opinions from outside experts on the current status of Java's security mechanisms, you may want to check the URL for the Princeton group (http://www.cs.princeton.edu/sip/) and the comp.risks newsgroup. The good side is that the Java team has said that they will have a "zero tolerance" for security bugs and will immediately go to work on fixing any bugs found in the applet security mechanism. In particular, by making public the internal specifications of how the Java interpreter works, Sun is making it far easier for people to find any bugs in Java's security features—essentially enlisting the outside community in the ever-so-subtle security bug detection. This makes one more confident that security bugs will be found as soon as possible. In any case, Java makes it extremely difficult to outwit its security mechanisms. The bugs found so far have been very subtle and (relatively) few in number.

Java graphics notes_icon.gif

Sun's URL for security-related issues is currently at http://java.oracle.com/sfaq/

Here is a sample of what Java's security features are supposed to keep a Java program from doing:
  1. Overrunning the runtime stack, like the infamous Internet worm did;

  2. Corrupting memory outside its own process space;

  3. Reading or writing local files when invoked through a security-conscious class loader, like a Web browser that has been programmed to forbid this kind of access.

All of these features are in place and for the most part seem to work as intended. Java is certainly the most secure coding language to date. But, caution is always in order. Though the bugs found in the security mechanism to date were not trivial to find and full details are often kept secret, still it may be impossible to prove that Java is secure. A number of security features have been added to Java over time. Since version 1.1, Java has the notion of digitally signed classes (see Volume 2). With a signed class, you can be sure of who wrote it. Any time you trust the author of the class, the class can be allowed more privileges on your machine.

Java graphics notes_icon.gif

A competing code delivery mechanism from Microsoft based on its ActiveX technology relies on digital signatures alone for security. Clearly this is not sufficient—as any user of Microsoft's own products can confirm, programs from well-known vendors do crash and in so doing, create damage. Java has a far stronger security model than ActiveX since it controls the app as it runs and stops it from wreaking havoc.

Architecture Neutral

The compiler generates an architecture-neutral object file format—the compiled code is executable on many processors, given the presence of the Java run time system. The Java compiler does this by generating bytecode instructions which have nothing to do with a particular computer architecture. Rather, they are designed to be both easy to interpret on any machine and easily translated into native machine code on the fly.

This is not a new idea. More than twenty years ago, both Niklaus Wirth's original implementation of Pascal and the UCSD Pascal system used the same technique. With the use of bytecodes, performance takes a major hit (but just-in-time compilation mitigates this in many cases). The designers of Java did an excellent job developing a bytecode instruction set that works well on today's most common computer architectures. And the codes have been designed to translate easily into actual machine instructions.

Portable

Unlike C and C++, there are no "implementation-dependent" aspects of the specification. The sizes of the primitive data types are specified, as is the behavior of arithmetic on them.

For example, an int in Java is always a 32-bit integer. In C/C++, int can mean a 16-bit integer, a 32-bit integer, or any other size that the compiler vendor likes. The only restriction is that the int type must have at least as many bytes as a short int and cannot have more bytes than a long int. Having a fixed size for number types eliminates a major porting headache. Binary data is stored and transmitted in a fixed format, eliminating the "big endian/little endian" confusion. Strings are saved in a standard Unicode format.

The libraries that are a part of the system define portable interfaces. For example, there is an abstract Window class and implementations of it for UNIX, Windows, and the Macintosh.

As anyone who has ever tried knows, it is an effort of heroic proportions to write a program that looks good on Windows, the Macintosh, and 10 flavors of UNIX. Java 1.0 made the heroic effort, delivering a simple toolkit that mapped common user-interface elements to a number of platforms. Unfortunately, the result was a library that, with a lot of work, could give barely acceptable results on different systems. (And there were often different bugs on the different platform graphics implementations.) But it was a start. There are many apps in which portability is more important than user interface slickness, and these apps did benefit from early versions of Java. By now, the user interface toolkit has been completely rewritten so that it no longer relies on the host user interface. The result is far more consistent and, we think, more attractive than in earlier versions of Java.

Interpreted

The Java interpreter can execute Java bytecodes directly on any machine to which the interpreter has been ported. Since linking is a more incremental and lightweight process, the development process can be much more rapid and exploratory.

Perhaps this is an advantage while developing an app, but it is clearly overstated. In any case, we have found the Java compiler that comes with the Java Software Development Kit (SDK) to be quite slow. (Some third party compilers, for example those by IBM, are quite a bit faster.) And recompilation speed is only one of the ingredients of a development environment with fast turnaround. If you are used to the speed of the development cycle of Visual Basic, you will likely be disappointed with the performance of Java development environments.

High Performance

While the performance of interpreted bytecodes is usually more than adequate, there are situations where higher performance is required. The bytecodes can be translated on the fly (at run time) into machine code for the particular CPU the app is running on.

If you use an interpreter to execute the bytecodes, "high performance" is not the term that we would use. However, on many platforms, there is also another form of compilation, the just-in-time (JIT) compilers. These work by compiling the bytecodes into native code once, caching the results, and then calling them again if needed. This approach speeds up commonly used code tremendously since one has to do the interpretation only once. Although still slightly slower than a true native code compiler, a just-in-time compiler can give you a 10- or even 20-fold speedup for some programs and will almost always be significantly faster than the Java interpreter. This technology is being improved continuously and may eventually yield results that cannot be matched by traditional compilation systems. For example, a just-in-time compiler can monitor which code is executed frequently and optimize just that code for speed.

Multithreaded

[The] benefits of multithreading are better interactive responsiveness and real-time behavior.

If you have ever tried to do multithreading in another language, you will be pleasantly surprised at how easy it is in Java. Threads in Java also have the capacity to take advantage of multiprocessor systems if the base operating system does so. On the downside, thread implementations on the major platforms differ widely, and Java makes no effort to be platform independent in this regard. Only the code for calling multithreading remains the same across machines; Java offloads the implementation of multithreading to the under-lying operating system or a thread library. (Threading will be covered in Volume 2.) Nonetheless, the ease of multithreading is one of the main reasons why Java is such an appealing language for server-side development.

Dynamic

In a number of ways, Java is a more dynamic language than C or C++. It was designed to adapt to an evolving environment. Libraries can freely add new methods and instance variables without any effect on their clients. In Java, finding out run time type information is straightforward.

This is an important feature in those situations where code needs to be added to a running program. A prime example is code that is downloaded from the Internet to run in a browser. In Java 1.0, finding out runtime type information was anything but straightforward, but current versions of Java give the programmer full insight into both the structure and behavior of its objects. This is extremely useful for systems that need to analyze objects at run time such as Java GUI builders, smart debuggers, pluggable components, and object databases.

Screenshot

Java ScreenShot
     
Top
 

Comments