Java
Java
A White Paper
A Sun Microsystems, Inc. Business 2550 Garcia Avenue Mountain View, CA 94043 U.S.A. 415 960-1300 FAX 415 969-9131
October 1995
A Sun Microsystems, Inc. Business 2550 Garcia Avenue Mountain View, CA 94043 U.S.A. 415 960-1300 FAX 415 969-9131
October 1995
Copyright Information 1995 Sun Microsystems, Inc. All rights reserved. 2550 Garcia Avenue, Mountain View, California 94043-1100 U.S.A. This BETA quality release and related documentation are protected by copyright and distributed under licenses restricting its use, copying, distribution, and decompilation. No part of this product or related documentation may be reproduced in any form by any means without prior written authorization of Sun and its licensors, if any. Portions of this product may be derived from the UNIX and Berkeley 4.3 BSD systems, licensed from UNIX System Laboratories, Inc., a wholly owned subsidiary of Novell, Inc., and the University of California, respectively. Third-party font software in this product is protected by copyright and licensed from Suns font suppliers. RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the United States Government is subject to the restrictions set forth in DFARS 252.227-7013 (c)(1)(ii) and FAR 52.227-19. The release described in this manual may be protected by one or more U.S. patents, foreign patents, or pending applications. TRADEMARKS Sun, the Sun logo, Sun Microsystems, Solaris, HotJava, and Java are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and certain other countries. The Duke character is a trademark of Sun Microsystems, Inc., and Copyright (c) 1992-1995 Sun Microsystems, Inc. All Rights Reserved. UNIX is a registered trademark in the United States and other countries, exclusively licensed through X/Open Company, Ltd. OPEN LOOK is a registered trademark of Novell, Inc. All other product names mentioned herein are the trademarks of their respective owners. All SPARC trademarks, including the SCD Compliant Logo, are trademarks or registered trademarks of SPARC International, Inc. SPARCstation, SPARCserver, SPARCengine, SPARCstorage, SPARCware, SPARCcenter, SPARCclassic, SPARCcluster, SPARCdesign, SPARC811, SPARCprinter, UltraSPARC, microSPARC, SPARCworks, and SPARCompiler are licensed exclusively to Sun Microsystems, Inc. Products bearing SPARC trademarks are based upon an architecture developed by Sun Microsystems, Inc. The OPEN LOOK and Sun Graphical User Interfaces were developed by Sun Microsystems, Inc. for its users and licensees. Sun acknowledges the pioneering efforts of Xerox in researching and developing the concept of visual or graphical user interfaces for the computer industry. Sun holds a non-exclusive license from Xerox to the Xerox Graphical User Interface, which license also covers Suns licensees who implement OPEN LOOK GUIs and otherwise comply with Suns written license agreements. X Window System is a trademark of the X Consortium. THIS PUBLICATION IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THIS PUBLICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION HEREIN; THESE CHANGES WILL BE INCORPORATED IN NEW EDITIONS OF THE PUBLICATION. SUN MICROSYSTEMS, INC. MAY MAKE IMPROVEMENTS AND/OR CHANGES IN THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THIS PUBLICATION AT ANY TIME.
Please Recycle
Contents
1. Introduction to Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 Beginnings of the Java Language Project. . . . . . . . . . . . . . 1.2 Design Goals of Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.1 Simple, Object Oriented, and Familiar . . . . . . . . . . . 1.2.2 Robust and Secure. . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.3 Architecture Neutral and Portable . . . . . . . . . . . . . . 1.2.4 High Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.5 Interpreted, Threaded, and Dynamic . . . . . . . . . . . . 1.3 The Java Base System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4 The Java Environmenta New Approach to Distributed Computing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. JavaSimple and Familiar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Main Features of the Java Language . . . . . . . . . . . . . . . . . 2.1.1 Primitive Data Types . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.2 Arithmetic and Relational Operators . . . . . . . . . . . . 2.1.3 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 12 12 13 14 14 15 15 16 17 18 20 20 21 21
iv
2.1.4 Strings. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.5 Multi-Level Break . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.6 Memory Management and Garbage Collection . . . 2.1.7 The Background Garbage Collector . . . . . . . . . . . . . 2.1.8 Integrated Thread Synchronization . . . . . . . . . . . . . 2.2 Features Removed from C and C++. . . . . . . . . . . . . . . . . . 2.2.1 No More Typedefs, Denes, or Preprocessor. . . . . . 2.2.2 No More Structures or Unions . . . . . . . . . . . . . . . . . 2.2.3 No More Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.4 No More Multiple Inheritance. . . . . . . . . . . . . . . . . . 2.2.5 No More Goto Statements . . . . . . . . . . . . . . . . . . . . . 2.2.6 No More Operator Overloading . . . . . . . . . . . . . . . . 2.2.7 No More Automatic Coercions . . . . . . . . . . . . . . . . . 2.2.8 No More Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3. Java is Object Oriented . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Object Technology in Java . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 What Are Objects? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Basics of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.2 Instantiating an Object from its Class. . . . . . . . . . . . 3.3.3 Constructors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.4 Methods and Messaging . . . . . . . . . . . . . . . . . . . . . . 3.3.5 Finalizers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22 23 24 25 25 26 26 27 27 28 29 29 29 30 30 32 33 33 34 35 35 36 37 39
3.3.6 Subclassing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.7 Access Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.8 Class Variables and Class Methods. . . . . . . . . . . . . . 3.3.9 Abstract Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. Architecture Neutral, Portable, and Robust . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Architecture Neutral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Byte Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Portable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Robust . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 Strict Compile-Time and Run-Time Checking. . . . . 4.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5. Interpreted and Dynamic. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1 Dynamic Loading and Binding. . . . . . . . . . . . . . . . . . . . . . 5.1.1 The Fragile Superclass Problem . . . . . . . . . . . . . . . . 5.1.2 Solving the Fragile Superclass Problem . . . . . . . . . . 5.1.3 Java Language Interfaces . . . . . . . . . . . . . . . . . . . . . . 5.1.4 Run-Time Representations . . . . . . . . . . . . . . . . . . . . . 5.2 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6. Security in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 Memory Allocation and Layout . . . . . . . . . . . . . . . . . . . . . 6.2 The Byte Code Verication Process . . . . . . . . . . . . . . . . . . 6.2.1 The Byte Code Verier . . . . . . . . . . . . . . . . . . . . . . . .
39 41 42 42 44 46 47 47 48 49 49 50 52 53 53 54 54 55 55 56 56 57 58
Contents
vi
6.3 Security Checks in the Bytecode Loader . . . . . . . . . . . . . . 6.4 Security in the Java Networking Package . . . . . . . . . . . . . 6.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7. Multithreading in Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1 Threads at the Java Language Level . . . . . . . . . . . . . . . . . 7.2 Integrated Thread Synchronization . . . . . . . . . . . . . . . . . . 7.3 Multithreading SupportConclusion . . . . . . . . . . . . . . . . 8. Performance and Comparisons. . . . . . . . . . . . . . . . . . . . . . . . . . 8.1 Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2 The Java Language Compared . . . . . . . . . . . . . . . . . . . . . . 8.3 A Major Benet of Java: Fast and Fearless Prototyping. . 8.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9. The HotJava World-Wide Web Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1 The Evolution of Cyberspace . . . . . . . . . . . . . . . . . . . . . . . 9.1.1 First Generation Browsers . . . . . . . . . . . . . . . . . . . . . 9.1.2 The HotJava BrowserA New Concept in Web Browsers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.3 The Essential Difference . . . . . . . . . . . . . . . . . . . . . . . 9.1.4 Dynamic Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.5 Dynamic Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.6 Dynamic Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 Freedom to Innovate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3 Implementation Details . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4 Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59 59 60 62 62 63 64 66 66 67 70 70 72 73 74 75 75 76 77 78 80 80 81
vii
9.4.1 The First Layerthe Java Language Interpreter. . . 9.4.2 The Next Layerthe Higher Level Protocols . . . . . 9.5 HotJavathe Promise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10. Further Reading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81 82 82 84
Contents
viii
ix
Introduction to Java
The Next Stage of the Known, Or a Completely New Paradigm? Taiichi SakaiyaThe Knowledge-Value Revolution
10
1
The tools you use to develop applications dont seem to help you much. Youre still coping with the same old problems; the fashionable new object-oriented techniques seem to have added new problems without solving the old ones. You say to yourself and your friends, There has to be a better way!
Your programming language is object oriented, yet its still dead simple. Your development cycle is much faster because Java is interpreted. The compile-link-load-test-crash-debug cycle is obsoletenow you just compile and run. Your applications are portable across multiple platforms. Write your applications once, and you never need to port themthey will run without modication on multiple operating systems and hardware architectures. Your applications are robust because the Java run-time system manages memory for you. Your interactive graphical applications have high performance because multiple concurrent threads of activity in your application are supported by the multithreading built into Java environment. Your applications are adaptable to changing environments because you can dynamically download code modules from anywhere on the network. Your end users can trust that your applications are secure, even though theyre downloading code from all over the Internet; the Java run-time system has built-in protection against viruses and tampering.
You dont need to dream about these features. Theyre here now. The Java Programming Language Environment provides a portable, interpreted, highperformance, simple, object-oriented programming language and supporting runtime environment. This introductory chapter provides you with a brief look at the main design goals of the Java system; the remainder of this paper examines the features of Java in more detail.
11
1
At the end of this paper youll nd a chapter that describes the HotJava Browser (HotJava for short). HotJava is an innovative World-Wide Web browser, and the rst major applications written using the Java environment. HotJava is the rst browser to dynamically download and execute Java code fragments from anywhere on the Internet, and to so so in a secure manner.
Introduction to Java
12
1
Operating on multiple platforms in heterogeneous networks invalidates the traditional schemes of binary distribution, release, upgrade, patch, and so on. To survive in this jungle, Java must be architecture neutral, portable, and dynamically adaptable. The Java system that emerged to meet these needs is simple, so it can be easily programmed by most developers; familiar, so that current developers can easily learn Java; object oriented, to take advantage of modern software development methodologies and to t into distributed client-server applications; multithreaded, for high performance in applications that need to perform multiple concurrent activities, such as multimedia; and interpreted, for maximum portability and dynamic capabilities. Together, the above requirements comprise quite a collection of buzzwords, so lets examine some of them and their respective benets before going on.
13
1
1.2.2 Robust and Secure
Java is designed for creating highly reliable software. It provides extensive compile-time checking, followed by a second level of run-time checking. Language features guide programmers towards reliable programming habits. The memory management modelno pointers or pointer arithmeticeliminates entire classes of programming errors that bedevil C and C++ programmers. You can develop Java language code with condence that the system will nd many errors quickly and that major problems wont lay dormant until after your production code has shipped. Java is designed to operate in distributed environments, which means that security is of paramount importance. With security features designed into the language and run-time system, Java lets you construct applications that cant be invaded from outside. In the networked environment, applications written in Java are secure from intrusion by unauthorized code attempting to get behind the scenes and create viruses or invade le systems.
Introduction to Java
14
1
The architecture-neutral and portable language environment of Java is known as the Java Virtual Machine. Its the specication of an abstract machine for which Java language compilers can generate code. Specic implementations of the Java Virtual Machine for specic hardware and software platforms then provide the concrete realization of the virtual machine. The Java Virtual Machine is based primarily on the POSIX interface specicationan industrystandard denition of a portable system interface. Implementing the Java Virtual Machine on new architectures is a relatively straightforward task as long as the target platform meets basic requirements such as support for multithreading.
15
1
Java supports multithreading at the language level with the addition of sophisticated synchronization primitives: the language library provides the Thread class, and the run-time system provides monitor and condition lock primitives. At the library level, moreover, Javas high-level system libraries have been written to be thread safe: the functionality provided by the libraries is available without conict to multiple concurrent threads of execution. While the Java compiler is strict in its compile-time static checking, the language and run-time system are dynamic in their linking stages. Classes are linked only as needed. New code modules can be linked in on demand from a variety of sources, even from sources across a network. In the case of the HotJava browser and similar applications, interactive executable code can be loaded from anywhere, which enables transparent updating of applications. The result is on-line services that constantly evolve; they can remain innovative and fresh, draw more customers, and spur the growth of electronic commerce on the Internet.
Introduction to Java
16
1
1.4 The Java Environmenta New Approach to Distributed Computing
Taken individually, the characteristics discussed above can be found in a variety of software development environments. Whats completely new is the manner in which Java and its run-time system have combined them to produce a exible and powerful programming system. Developing your applications using Java results in software that is portable across multiple machine architectures, operating systems, and graphical user interfaces, secure, and high performance. With Java, your job as a software developer is much easieryou focus your full attention on the end goal of shipping innovative products on time, based on the solid foundation of Java. The better way to develop software is here, now, brought to you by the Java language environment.
17
You know youve achieved perfection in design, Not when you have nothing more to add, But when you have nothing more to take away. Antoine de Saint Exupery.
In his science-ction novel, The Rolling Stones, Robert A. Heinlein comments: Every technology goes through three stages: rst a crudely simple and quite unsatisfactory gadget; second, an enormously complicated group of gadgets designed to overcome the shortcomings of the original and achieving thereby somewhat satisfactory performance through extremely complex compromise; third, a nal proper design therefrom. Heinleins comment could well describe the evolution of many programming languages. Java presents a new viewpoint in the evolution of programming languagescreation of a small and simple language thats still sufciently comprehensive to address a wide variety of software application development. While Java supercially like C and C++, Java gained its simplicity from the systematic removal of features from its predecessors. This chapter discusses two of the primary design features of Java, namely, its simple (from removing features) and familiar (because it looks like C and C++). The next chapter
18
2
discusses Javas object-oriented features in more detail. At the end of this chapter youll nd a discussion on features eliminated from C and C++ in the evolution of Java.
Design Goals
Simplicity is one of Javas overriding design goals. Simplicity and removal of many features of dubious worth from its C and C++-based ancestors keep Java relatively small and reduce the programmers burden in producing reliable applications. To this end, Java design team examined many aspects of the modern C and C++ languages* to determine features that could be eliminated in the context of modern object-oriented programming. Another major design goal is that Java look familiar to a majority of programmers in the personal computer and workstation arenas, where a large fraction of system programmers and application programmers are familiar with C and C++. Thus, Java looks like C++. Programmers familiar with C, Objective C, C++, Eiffel, Ada, and related languages should nd their Java language learning curve quite shorton the order of a couple of weeks. To illustrate the simple and familiar aspects of Java, we follow the tradition of a long line of illustrious programming books by showing you the HelloWorld program. Its about the simplest program you can write that actually does something. Heres HelloWorld implemented in Java.
class HelloWorld { static public void main(String args[]) { System.out.println("Hello world!"); } }
This example declares a class named HelloWorld. Classes are discussed in the next chapter on object-oriented programming, but in general we assume the reader is familiar with object technology and understands the basics of classes, objects, instance variables, and methods. Within the HelloWorld class, we declare a single method called main() which in turn contains a single method invocation to display the string "Hello world!" on the standard output. The statement that prints "Hello world!" does so by
19
2
invoking the println method of the out object. The out object is a class variable in the System class that performs output operations on les. Thats all there is to HelloWorld.
20
2
you get a Unicode (16-bit unsigned value) type thats initialized to the Unicode value of the character Q. By adopting the Unicode character set standard for its character data type, Java language applications are amenable to internationalization and localization, greatly expanding the market for worldwide applications.
2.1.3 Arrays
In contrast to C and C++, Java language arrays are rst-class language objects. An array in Java is a real object with a run-time representation. You can declare and allocate arrays of any type, and you can allocate arrays of arrays to obtain multi-dimensional arrays. You declare an array of, say, Points (a class youve declared elsewhere) with a declaration like this:
Point myPoints[];
This code states that myPoints is an uninitialized array of Points. At this time, the only storage allocated for myPoints is a reference handle. At some future time you must allocate the amount of storage you need, as in:
myPoints = new Point[10];
21
2
to allocate an array of ten references to Points that are initialized to the null reference. Notice that this allocation of an array doesnt actually allocate any objects of the Point class for you; you will have to also allocate the Point objects, something like this:
int i;
Access to elements of myPoints can be performed via the normal C-style indexing, but all array accesses are checked to ensure that their indices are within the range of the array. An exception is generated if the index is outside the bounds of the array. To get the length of an array, use the length() accessor method on the array object whose length you wish to know: myPoints.length() returns the number of elements in myPoints. For instance, the code fragment:
howMany = myPoints.length();
would assign the value 10 to the howMany variable. The C notion of a pointer to an array of memory elements is gone, and with it, the arbitrary pointer arithmetic that leads to unreliable code in C. No longer can you walk off the end of an array, possibly trashing memory and leading to the famous delayed-crash syndrome, where a memory-access violation today manifests itself hours or days later. Programmers can be condent that array checking in Java will lead to more robust and reliable code.
2.1.4 Strings
Strings are Java language objects, not pseudo-arrays of characters as in C. There are actually two kinds of string objects: the String class is for read-only (immutable) objects. The StringBuffer class is for string objects you wish to modify (mutable string objects). Although strings are Java language objects, Java compiler follows the C tradition of providing a syntactic convenience that C programmers have enjoyed with C-style strings, namely, the Java compiler understands that a string of characters enclosed in double quote signs is to be instantiated as a String object. Thus, the declaration:
String hello = "Hello world!";
22
2
instantiates an object of the String class behind the scenes and initializes it with a character string containing the Unicode character representation of "Hello world!". Java has extended the meaning of the + operator to indicate string concatenation. Thus you can write statements like:
System.out.println("There are " + num + " characters in the file.");
This code fragment concatenates the string "There are " with the result of converting the numeric value num to a string, and concatenates that with the string " characters in the file.". Then it prints the result of those concatenations on the standard output. Just as with array objects, String objects provide a length() accessor method to obtain the number of characters in the string.
The continue test statement is inside a for loop nested inside another for loop. By referencing the label test, the continue statement passes control to the outer for statement. In traditional C, continue statements can only continue the immediately enclosing block; to continue or exit outer blocks, programmers have traditionally either used auxiliary Boolean variables whose only purpose is to determine if the outer block is to be continued or exited;
23
2
alternatively, programmers have (mis)used the goto statement to exit out of nested blocks. Use of labelled blocks in Java leads to considerable simplication in programming effort and a major reduction in maintenance. The notion of labelled blocks dates back to the mid-1970s, but it hasnt caught on to any large extent in modern programming languages. Perl is another modern programming language that implements the concept of labelled blocks. Perls next label and last label are equivalent to continue label and break label statements in Java.
24
2
dest.appendChar(source.charAt(i)); } return dest.toString(); } }
The variable dest is used as a temporary object reference during the execution of the reverseIt method. When dest goes out of scope (the reverseIt method returns), the reference to that object has gone away and its then a candidate for garbage collection.
25
2
2.2 Features Removed from C and C++
The earlier part of this chapter concentrated on the principal features of Java. This section discusses features removed from C and C++ in the evolution of Java. The rst step was to eliminate redundancy from C and C++. In many ways, the C language evolved into a collection of overlapping features, providing too many ways to say the same thing, while in many cases not providing needed features. C++, in an attempt to add classes in C, merely added more redundancy while retaining many of the inherent problems of C.
26
2
2.2.2 No More Structures or Unions
Java has no structures or unions as complex data types. You dont need structures and unions when you have classes; you can achieve the same effect simply by declaring a class with the appropriate instance variables. The code fragment below declares a class called Point.
class Point extends Object { double x; double y; methods to access the instance variables }
The following code fragment declares a class called Rectangle, that uses objects of the Point class as instance variables.
class Rectangle extends Object { Point lowerLeft; Point upperRight; methods to access the instance variables }
In C youd dene these classes as structures. In Java, you simply declare classes. You can make the instance variables as private or as public as you wish, depending on how much you wish to hide the details of the implementation from other objects.
27
2
public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } public double x() { return x; } public double y() { return x; } }
If the x and y instance variables are private to this class, the only means to access them is via the public methods of the class. Heres how youd use objects of the Point class from within, say, an object of the Rectangle class:
class Rectangle extends Object { Point lowerLeft; Point upperRight; public void setEmptyRect() { lowerLeft.setX(0.0); lowerLeft.setY(0.0); upperRight.setX(0.0); upperRight.setY(0.0); } }
Its not to say that functions and procedures are inherently wrong. But given classes and methods, were now down to only one way to express a given task. By eliminating functions, your job as a programmer is immensely simplied: you work only with classes and their methods.
28
2
An interface is not a denition of an object. Rather, its a denition of a set of methods that one or more objects will implement. An important issue of interfaces is that they declare only methods and constants. No variables may be dened in interfaces.
The assignment of myFloat to myInt would result in a compiler error indicating a possible loss of precision and that you must use an explicit cast. Thus, you should re-write the code fragments as:
29
2
int myInt; double myFloat = 3.14159; myInt = (int)myFloat;
2.3 Summary
To sum up this chapter, Java is:
Simplethe number of language constructs you need to understand to get your job done is minimal. FamiliarJava looks like C and C++ while discarding the overwhelming complexities of those languages.
Now that youve seen how Java was simplied by removal of features from its predecessors, read the next chapter for a discussion on the object-oriented features of Java.
30
31
3
My Object All Sublime I Will Achieve in Time Gilbert and SullivanThe Mikado
To stay abreast of modern software development practices, Java is object oriented from the ground up. The point of designing an object-oriented language is not simply to jump on the latest programming fad. The objectoriented paradigm meshes well with the needs of client-server and distributed software. Benets of object technology are rapidly becoming realized as more organizations move their applications to the distributed client-server model. Unfortunately, object oriented remains misunderstood, over-marketed as the silver bullet that will solve all our software ills, or takes on the trappings of a religion. The cynics view of object-oriented programming is that its just a new way to organize your source code. While there may be some merit to this view, it doesnt tell the whole story, because you can achieve results with objectoriented programming techniques that you cant with procedural techniques. An important characteristic that distinguishes objects from ordinary procedures or functions is that an object can have a lifetime greater than that of the object that created it. This aspect of objects is subtle and mostly
32
3
overlooked.In the distributed client-server world, this creates the potential for objects to be created in one place, passed around networks, and stored elsewhere, possibly in databases, to be retrieved for future work. As an object-oriented language, Java draws on the best concepts and features of previous object-oriented languages, primarily Eiffel, SmallTalk, Objective C, and C++. Java goes beyond C++ in both extending the object model and removing the major complexities of C++. With the exception of its primitive data types, everything in Java is an object, and even the primitive types can be encapsulated within objects if the need arises.
Encapsulationimplements information hiding and modularity (abstraction) Polymorphismthe same message sent to different objects results in behavior thats dependent on the nature of the object receiving the message Inheritanceyou dene new classes and behavior based on existing classes to obtain code re-use and code organization Dynamic bindingobjects could come from anywhere, possibly across the network. You need to be able to send messages to objects without having to know their specic type at the time you write your code. Dynamic binding provides maximum exibility while a program is executing
Java meets these requirements nicely, and adds considerable run-time support to make your software development job easier.
33
3
and spreadsheet cells, property lists, menus, and so on. These objects have state and behavior. You can represent all these things with software constructs called objects, which can also be dened by their state and their behavior. In your everyday transportation needs, a car can be modelled by an object. A car has state (how fast its going, in which direction, its fuel consumption, and so on) and behavior (starts, stops, turns, slides, and runs into trees). You drive your car to your ofce, where you track your stock portfolio. In your daily interactions with the stock markets, a stock can be modelled by an object. A stock has state (daily high, daily low, open price, close price, earnings per share, relative strength), and behavior (changes value, performs splits, has dividends). After watching your stock decline in price, you repair to the cafe to console yourself with a cup of good hot coffee. The espresso machine can be modelled as an object. It has state (water temperature, amount of coffee in the hopper) and it has behavior (emits steam, makes noise, and brews a perfect cup of java).
Instance Variables
In the programming implementation of an object, its state is dened by its instance variables. Instance variables are private to the object. Unless explicitly made public or made available to other friendly classes, an objects instance variables are inaccessible from outside the object. An objects behavior is dened by its methods. Methods manipulate the instance variables to create new state; an objects methods can also create new objects. The small picture to the left is a commonly used graphical representation of an object. The diagram illustrates the conceptual structure of a software objectits kind of like a cell, with an outer membrane thats its interface to the world, and an inner nucleus thats protected by the outer membrane. An objects instance variables (data) are packaged, or encapsulated, within the object. The instance variables are surrounded by the objects methods. With certain well-dened exceptions, the objects methods are the only means by which other objects can access or alter its instance variables. In Java, classes can declare their instance variables to be public, in which cases the instance variables are globally accessible to other objects. Declarations of accessibility are covered in later in Access Speciers.
Method
34
3
3.3.1 Classes
A class is a software construct that denes the instance variables and methods of an object. A class in and of itself is not an object. A class is a template that denes how an object will look and behave when the object is created or instantiated from the specication declared by the class. You obtain concrete objects by instantiating a previously dened class. You can instantiate many objects from one class denition, just as you can construct many houses that area all the same from a single architects drawing. Heres the basic declaration of a very simple class called Point
class Point extends Object { public double x; /* instance variable public double y; /* instance variable } */ */
As mentioned, this declaration merely denes a template from which real objects can be instantiated, as described next.
Now, you can access the variables of this Point object by referring to the names of the variables, qualied with the name of the object:
myPoint.x = 10.0; myPoint.y = 25.7;
This referencing scheme, similar to a C structure reference, works because the instance variables of Point were declared public in the class declaration. Had the instance variables not been declared public, objects outside of the package within which Point was declared could not access its instance variables in this direct manner. The Point class declaration would then need to provide accessor methods to set and get its variables. This topic is discussed in a little more detail after the discussion on constructors.
35
3
3.3.3 Constructors
When you declare a class in Java, you can declare optional constructors that perform initialization when you instantiate objects from that class. You can also declare an optional nalizer, discussed later. Lets go back to our Point class from before:
class Point extends Object { public double x; /* instance variable public double y; /* instance variable Point() { x = 0.0; y = 0.0; } /* */ */ */
/* constructor to initialize to specific value */ Point(double x, double y) { this.x = x; /* set instance variables to passed parameters this.y = y; } }
*/
Methods with the same name as the class as in the code fragment are called constructors. When you create (instantiate) an object of the Point class, the constructor method is invoked to perform any initialization thats neededin this case, to set the instance variables to an initial state. This example is a variation on the Point class from before. Now, when you wish to create and initialize Point objects, you can get them initialized to their default values, or you can initialize them to specic values:
Point Point lowerLeft; upperRight;
lowerLeft = new Point(); /* initialize to default zero value */ upperRight = new Point(100.0, 200.0); /* initialize to non- zero */
The specic constructor thats used when creating a new Point object is determined from the type and number of parameters in the new invocation.
36
3
The this Variable
Whats the this variable in the examples above? this refers to the object youre in right now. In other words, this refers to the receiving object. You use this to clarify which variable youre referring to. In the two-parameter Point method, this.x means the x instance variable of this object, rather than the x parameter to the Point method. In the example above, the constructors are simply conveniences for the Point class. There are situations, however, where constructors are necessary, especially in cases where the object being instantiated must itself instantiate other objects. Lets illustrate this by declaring a Rectangle class that uses two Point objects to dene its bounds:
class Rectangle extends Object { private Point lowerLeft; private Point upperRight; Rectangle() { lowerLeft = new Point(); upperRight = new Point(); } . . . instance methods appear in here . . . }
In this example, the Rectangle() constructor is vitally necessary to ensure that the two Point objects are instantiated at the time a Rectangle object is instantiated, otherwise, the Rectangle object would subsequently try to reference points that have not yet been allocated, and would fail.
If an object wants another object to do some work on its behalf, then in the parlance of object-oriented programming, the rst object sends a message to the second object. In response, the second object selects the appropriate method to invoke. Java method invocations look similar to functions in C and C++. Using the message passing paradigms of object-oriented programming, you can build entire networks and webs of objects that pass messages between them to change state. This programming technique is one of the best ways to
37
3
create models and simulations of complex real-world systems. Lets redene the declaration of the Point class from above such that its instance variables are private, and supply it with accessor methods to access those variables.
class Point extends Object { private double x; /* private double y; /* Point() { /* x = 0.0; y = 0.0; } instance variable instance variable */ */ */
/* constructor to initialize to specific value */ Point(double x, double y) { this.x = x; this.y = y; } public void setX(double x) { /* accessor method */ this.x = x; } public void setY(double y) { /* accessor method */ this.y = y; } public double getX() { /* accessor method */ return x; } public double getY() { /* accessor method */ return y; } }
These method declarations provides the avor of how the Point class provides access to its variables from the outside world. Another object that wants to manipulate the instance variables of Point objects must now do so via the accessor methods:
Point myPoint; // // // declares a variable to refer to a Point object allocates an instance of a Point object sets the x variable via the accessor method
Making instance variables public or private is a design tradeoff the designer makes when declaring the classes. By making instance variables public, you are exposing some of the details of the implementation of the class, thereby providing higher efciency and conciseness of expression at the possible
38
3
expense of hindering future maintenance efforts. By hiding details of the internal implementation of a class, you have the potential to change the implementation of the class in the future without breaking any code that uses that class.
3.3.5 Finalizers
You can also declare an optional nalizer that will perform necessary tear-down actions when the garbage collector is about to free an object. This code fragment illustrates a finalize method in a class.
/** * Close the stream when garbage is collected. */ protected void finalize() { try { file.close(); } catch (Exception e) { } }
This finalize method will be invoked when the object is about to be garbage collected, which means that the object must shut itself down in an orderly fashion. In the particular code fragment above, the finalize method merely closes an I/O le stream that was used by the object, to ensure that the le descriptor for the stream is closed.
3.3.6 Subclassing
Subclassing is the mechanism by which new and enhanced objects can be dened in terms of existing objects. One example: a zebra is a horse with stripes. If you wish to create a zebra object, you notice that a zebra is kind of like a horse, only with stripes. In object-oriented terms, youd create a new class called Zebra, which is a subclass of the Horse class. In Java language terms, youd do something like this:
class Zebra extends Horse { Your new instance variables and new methods go here }
The denition of Horse, wherever it is, would dene all the methods to describe the behavior of a horse: eat, neigh, trot, gallop, buck, and so on. The only method you need to override is the method for drawing the hide. You
39
3
gain the benet of already written code that does all the workyou dont have to re-invent the wheel, or in this case, the hoof. The extends keyword tells the Java compiler that Zebra is a subclass of Horse. Zebra is said to be a derived classits derived from Horse, which is called a base class. Heres an example of subclassing a variant of our Point class from previous examples to create a new three-dimensional point called ThreePoint:
class Point extends Object { protected double x; /* protected double y; /* Point() { /* x = 0.0; y = 0.0; } } class ThreePoint extends Point { protected double z; /* the z coordinate of the point */ instance variable instance variable */ */ */
ThreePoint() { /* default constructor */ x = 0.0; /* initialize the coordinates */ y = 0.0; z = 0.0; } ThreePoint(double x, double y, double z) {/* specific constructor */ this.x = x; /* initialize the coordinates */ this.y = y; this.z = z; } }
Notice that ThreePoint adds a new instance variable for the z coordinate of the point. The x and y instance variables are inherited from the original Point class, so theres no need to declare them in ThreePoint. However, notice we had to make Points instance variables protected instead of private as in the previous examples. Had we left Points instance variables private, even its subclasses would be unable to access them, and the compilation would fail. Subclassing enables you to use existing code thats already been developed and, much more important, tested, for a more generic case. You override the parts of the class you need for your specic behavior. Thus, subclassing gains
40
3
you reuse of existing codeyou save on design, development, and testing. The Java run-time system provides several libraries of utility functions that are tested and are also thread safe.
41
3
3.3.8 Class Variables and Class Methods
Java follows conventions from other object-oriented languages in providing class methods and class variables. Normally, variables you declare in a class denition are instance variablesthere is one of those variables in every separate object thats created (instantiated) from the class. A class variable, on the other hand, is local to the class itselftheres only a single copy of the variable and its shared by every object you instantiate from the class. To declare class variables and class methods, you declare them as static. This short code fragment illustrates the declaration of class variables:
class Rectangle extends Object { static final int version = 2; static final int revision = 0; }
The Rectangle class declares two static variables to dene the version and revision level of this class. Now, every instance of Rectangle that you create from this class will share these same variables. Notice theyre also dened as final because you want them to be constants. Class methods are methods that are common to an entire class. When would you use class methods? Usually, when you have behavior thats common to every object of a class. For example, suppose you have a Window class. A useful item of information you can ask the class is the width of the border around the window. Theres no point in having an instance method to obtain this information thats shared by every instance of Windowit makes more sense to have just one class method to return the border width. Class methods can operate only on class variables. Class methods cant access instance variables, nor can they invoke instance methods. Like class variables, you declare class methods by dening them as static.
42
3
This all sounds wonderfully, well, abstract, so why would you need an abstract superclass? Lets look at a concrete example, no pun intended. Lets suppose youre going to a restaurant for dinner, and you decide that tonight you want to eat sh. Well, sh is somewhat abstractyou generally wouldnt just order sh; the waiter is highly likely to ask you what specic kind of sh you want. When you actually get to the restaurant, you will nd out what kind of sh they have, and order a specic sh, say, sturgeon, or salmon, or opakapaka. In the world of objects, an abstract class is like generic shthe abstract class denes generic state and generic behavior, but youll never see a real live implementation of an abstract class. What you will see is a concrete subclass of the abstract class, just as opakapaka is a specic (concrete) kind of sh. Suppose you are creating a drawing application. The initial cut of your application can draw rectangles, lines, circles, polygons, and so on. Furthermore, you have a series of operations you can perform on the shapesmove, reshape, rotate, ll color, and so on. You could make each of these graphic shapes a separate classyoud have a Rectangle class, a Line class, and so on. Each class needs instance variables to dene its position, size, color, rotation and so on, which in turn dictates methods to set and get at those variables. At this point, you realize you can collect all the instance variables into a single abstract superclass called Graphical, and implement most of the methods to manipulate the variables in that abstract superclass. The skeleton of your abstract superclass might look something like this:
abstract class Graphic extends Object { protected Point lowerLeft; // lower left of bounding box protected Point upperRight; // upper right of bounding box . . . more instance variables . . . public void setPosition(Point ll, Point ur) { lowerLeft = ll; upperRight = ur; } abstract void drawMyself(); // abstract method } }
43
3
Now, you cant instantiate the Graphical class, because its declared abstract. You can only instantiate a subclass of it. When you implement the Rectangle class or the Circle class, youd extend (subclass) Graphical. Within Rectangle, youd provide a concrete implementation of the drawMySelf() method that draws a rectangle, because the denition of drawMySelf() must by necessity be unique to each shape inherited from the Graphical class. Lets see a small fragment of the Rectangle class declaration, where its drawMySelf() method operates in a somewhat PostScripty fashion:
abstract class Rectangle extends Graphical { void drawMySelf() { // really does the drawing moveTo(lowerLeft.x, lowerLeft.y); lineTo(upperRight.x, lowerLeft.y); lineTo(upperRight.x, upperRight.y) lineTo(lowerLeft.x, upperRight.y); . . . and so on and so on . . . } }
Notice, however, that in the declaration of the Graphical class, the setPosition() method was declared as a regular (public void) method. All methods that can be implemented by the abstract superclass can be declared there and their implementations dened at that time. Then, every class that inherits from the abstract superclass will also inherit those methods. You can continue in this way adding new shapes that are subclasses of Graphical, and most of the time, all you ever need to implement is the methods that are unique to the specic shape. You gain the benet of re-using all the code that was dened inside the abstract superclass.
3.4 Summary
This chapter has conveyed the essential aspects of Java as an object-oriented language. To sum up:
Classes dene templates from which you instantiate (create) distinct concrete objects. Instance variables hold the state of a specic object.
44
3
Objects communicate by sending messages to each other. Objects respond to messages by selecting a method to execute. Methods dene the behavior of objects instantiated from a class. It is an objects methods that manipulate its instance variables. Unlike regular procedural languages, classes in an object-oriented language may have methods with the same names as other classes. A given object responds to a message in ways determined by the nature of that object, providing polymorphic behavior. Subclassing provides the means by which a new class can inherit instance variables and methods from any already dened class. The newly declared class can add new instance variables (extra state), can add new methods (new behavior), or can override the methods of its superclass (different behavior). Subclassing provides code reuse.
Taken together, the concepts of object-oriented programming create a powerful and simple paradigm for software developers to share and re-use code and build on the work of others.
45
With the phenomenal growth of networks, todays developers must think distributed. Applicationseven parts of applicationsmust be able to migrate easily to a wide variety of computer systems, a wide variety of hardware architectures, and a wide variety of operating system architectures. They must operate with a plethora of graphical user interfaces. Clearly, applications must be able to execute anywhere on the network without prior knowledge of the target hardware and software platform. If application developers are forced to develop for specic target platforms, the binary distribution problem quickly becomes unmanageable. Various and sundry methods have been employed to overcome the problem, such as creating fat binaries that adapt to the specic hardware architecture, but such methods are not only clumsy but are still geared to a specic operating system. To solve the binary-distribution problem, software applications and fragments of applications must be architecture neutral and portable. Reliability is also at a high premium in the distributed world. Code from anywhere on the network should work robustly with low probabilities of creating crashes in applications that import fragments of code. This chapter describes the ways in which Java has addressed the issues of architecture neutrality, portability, and reliability.
46
4
4.1 Architecture Neutral
The solution that the Java system adopts to solve the binary-distribution problem is a binary code format thats independent of hardware architectures, operating system interfaces, and window systems. The format of this system-independent binary code is architecture neutral. If the Java run-time system is made available on a given hardware and software platform, an application written in Java can then execute on that platform without the need to perform any special porting work for that application.
47
4
4.2 Portable
The primary benet of the interpreted byte code approach is that compiled Java language programs are portable to any system on which the Java interpreter and run-time system have been implemented. The architecture-neutral aspect discussed above is one major step towards being portable, but theres more to it than that. C and C++ both suffer from the defect of designating many fundamental data types as implementation dependent. Programmers labor to ensure that programs are portable across architectures by programming to a lowest common denominator. Java eliminates this issue by dening standard behavior that will apply to the data types across all platforms. Java species the sizes of all its primitive data types and the behavior of arithmetic on them. Here are the data types: byte short int long float double char 8-bit twos complement 16-bit twos complement 32-bit twos complement 64-bit twos complement 32-bit IEEE 754 oating point 64-bit IEEE 754 oating point 16-bit Unicode character
The data types and sizes described above are standard across all implementations of Java. These choices are reasonable given current microprocessor architectures because essentially all central processor architectures in use today share these characteristics. That is, most modern processors can support twos-complement arithmetic in 8-bit to 64-bit integer formats, and most modern processors support single- and double-precision oating point. The Java environment itself is readily portable to new architectures and operating systems. The Java compiler is written in Java. The Java run-time system is written in ANSI C with a clean portability boundary which is essentially POSIX-compliant. There are no implementation-dependent notes in the Java language specication.
48
4
4.3 Robust
Java is intended for developing software that must be robust, highly reliable, and secure, in a variety of ways. Theres strong emphasis on early checking for possible problems, as well as later dynamic (run-time) checking, to eliminate error-prone situations.
49
4
4.4 Summary
Javaan architecture-neutral and portable programming languageprovides an attractive and simple solution to the problem of distributing your applications across heterogeneous network-based computing platforms. In addition, the simplicity and robustness of the underlying Java language results in higher quality, reliable applications in which users can have a high level of condence. The next chapter contains a brief discussion of Javas interpreted implementation.
50
51
Programmers using traditional software development tools have become resigned to the articial edit-compile-link-load-throw-the-application-off-thecliff-let-it-crash-and-start-all-over-again style of current development practice. Additionally, keeping track of what must be recompiled when a declaration changes somewhere else strains the capabilities of development toolseven fancy make-style tools such as found on UNIX systems. This development approach bogs down as the code bases of applications grow to hundreds of thousands of lines. Better methods of fast and fearless prototyping and development are needed. The Java language environment is one of those better ways, because its interpreted and dynamic. As discussed in the previous chapter on architecture-neutrality, the Java compiler generates byte codes for the Java Virtual Machine*, which was introduced briey in Chapter 4. The notion of a virtual interpreted machine is not new. But the Java language brings the concepts into the realm of secure, distributed, network-based systems. The Java language virtual machine is a strictly dened virtual machine for which an interpreter must be available for each hardware architecture and operating system on which you wish to run Java language applications. Once
* One of the ancestors of the virtual machine concept was the UCSD P System, developed by Kenneth Bowles at the University of California at San Diego in the late 1970s.
52
5
you have the Java language interpreter and run-time support available on a given hardware and operating system platform, you can run any Java language application from anywhere, always assuming the specic Java language application is written in a portable manner. The notion of a separate link phase after compilation is pretty well absent from the Java environment. Linking, which is actually the process of loading new classes by the Class Loader, is a more incremental and lightweight process. The concomitant speedup in your development cycle means that your development process can be much more rapid and exploratory, and because of the robust nature of the Java language and run-time system, you will catch bugs at a much earlier phase of the cycle.
53
5
effectively means not using any of the languages object-oriented features directly. By avoiding the object-oriented features of C++, developers defeat the goal of re-usable software ICs.
54
5
5.1.4 Run-Time Representations
Classes in the Java language have a run-time representation. There is a class named Class, instances of which contain run-time class denitions. If youre handed an object, you can nd out what class it belongs to. In a C or C++ program, you may be handed a pointer to an object, but if you dont know what type of object it is, you have no way to nd out. In the Java language, nding out based on the run-time type information is straightforward. It is also possible to look up the denition of a class given a string containing its name. This means that you can compute a data type name and easily have it dynamically-linked into the running system.
5.2 Summary
The interpreted and dynamic nature of Java provides several benets:
The interpreted environment enables fast prototyping without waiting for the traditional compile and link cycle, The environment is dynamically extensible, whereby classes are loaded on the y as required, The fragile superclass problem that plagues C++ developers is eliminated because of deferral of memory layout decisions to run time.
55
Security in Java
Security commands a high premium in the growing use of the Internet for products and services ranging from electronic distribution of software and multimedia content, to digital cash. The area of security with which were concerned here is how the Java compiler and run-time system restrict application programmers from creating subversive code. The Java language compiler and run-time system implement several layers of defense against potentially incorrect code. The environment starts with the assumption that nothing is to be trusted, and proceeds accordingly. The next few sections discuss the Java security models in greater detail.
56
6
cant forge pointers to memory, because the memory allocation and referencing model is completely opaque to the programmer and controlled entirely by the underlying run-time system. Very late binding of structures to memory means that programmers cant infer the physical memory layout of a class by looking at its declaration. By removing the C and C++ memory layout and pointer models, the Java language has eliminated the programmers ability to get behind the scenes and manufacture pointers to memory. These features must be viewed as positive benets rather than a restriction on the programmer, because they ultimately lead to more reliable and secure applications.
it doesnt forge pointers, it doesnt violate access restrictions, it accesses objects as what they are (for example, InputStream objects are always used as InputStreams and never as anything else).
A language that is safe, plus run-time verication of generated code, establishes a base set of guarantees that interfaces cannot be violated.
57
6
6.2.1 The Byte Code Verier
The bytecode verier traverses the bytecodes, constructs the type state information, and veries the types of the parameters to all the bytecode instructions.
Compile Time Java Source
byte codes move through network or file system
Java Compiler
hardware
The illustration shows the ow of data and control from Java language source code through the Java compiler, to the bytecode verier and hence on to the Java interpreter. The important issue is that the Java bytecode loader and the bytecode verier make no assumptions about the primary source of the bytecode streamthe code may have come from the local system, or it may have travelled halfway around the planet. The bytecode verier acts as a sort of gatekeeper: it ensures that code passed to the Java interpreter is in a t state to be executed and can run without fear of breaking the Java interpreter. Imported code is not allowed to execute by any means until after it has passed the veriers tests. Once the verier is done, a number of important properties are known:
Security in Java
58
6
The types of the parameters of all bytecode instructions are known to always be correct Object eld accesses are known to be legalprivate, public, or protected
While all this checking appears excruciatingly detailed, by the time the bytecode verier has done its work, the Java interpreter can proceed, knowing that the code will run securely. Knowing these properties makes the Java interpreter much faster, because it doesnt have to check anything. There are no operand type checks and no stack overow checks. The interpreter can thus function at full speed without compromising reliability.
59
Disallow all network accesses Allow network accesses to only the hosts from which the code was imported
6
Allow network accesses only outside the rewall if the code came from outside Allow all network accesses
6.5 Summary
Java is secure to survive in the network-based environment. The architectureneutral and portable aspects of the Java language make it the ideal development language to meet the challenges of distributing dynamically extensible software across networks.
Security in Java
60
61
Multithreading in Java
Sophisticated computer users become impatient with the do-one-thing-at-atime mindset of the average personal computer. Users perceive that their world is full of multiple events all happening at once, and they like to have their computers work the same way. Unfortunately, writing programs that deal with many things happening at once can be much more difcult than writing in the conventional single-threaded C and C++ style. You can write multithreaded applications in languages such as C and C++, but the level of difculty goes up by orders of magnitude, and even then there are no assurances that vendors libraries are thread-safe. The term thread-safe means that a given library function is implemented in such a manner that it can be executed by multiple concurrent threads of execution. The major problem with explicitly programmed thread support is that you can never be quite sure you have acquired the locks you need and released them again at the right time. If you return from a method prematurely, for instance, or if an exception is raised, for another instance, your lock has not been released; deadlock is the usual result.
62
7
downloading a text le from a server, multithreading is the way to obtain fast, lightweight concurrency within a single process space. Threads are sometimes also called lightweight processes or execution contexts. Threads are an essential keystone of Java. The Java library provides a Thread class that supports a rich collection of methods to start a thread, run a thread, stop a thread, and check on a threads status. Java thread support includes a sophisticated set of synchronization primitives based on the widely used monitor and condition variable paradigm introduced twenty years ago by C.A.R. Hoare and implemented in a production setting in Xerox PARCs Cedar/Mesa system. Integrating support for threads into the language makes them much easier to use and more robust. Much of the style of Javas integration of threads was modelled after Cedar and Mesa. Javas threads are pre-emptive, and depending on platform on which the Java interpreter executes, threads can also be time-sliced. On systems that dont support time-slicing, once a thread has started, the only way it will relinquish control of the processor is if another thread of a higher priority takes control of the processor. If your applications are likely to be compute-intensive, you might consider how to give up control periodically by using the yield() method to give other threads a chance to run; doing so will ensure better interactive response for graphical applications.
63
7
kicker = null; } } private synchronized void startSort() { if (kicker == null || !kicker.isAlive()) { kicker = new Thread(this); kicker.start(); } }
The stop and startSort methods are declared to be synchronizedthey cant run concurrently, enabling them to maintain consistent state in the shared kicker variable. When a synchronized method is entered, it acquires a monitor on the current object. The monitor precludes any other synchronized methods in that object from running. When a synchronized method returns by any means, its monitor is released. Other synchronized methods within the same object are now free to run. If youre writing Java applications, you should take care to implement your classes and methods so theyre thread-safe, in the same way that Java run-time libraries are thread-safe. If you wish your objects to be thread-safe, any methods that may change the values of instance variables should be declared synchronized. This ensures that only one method can change the state of an object at any time. Java monitors are re-entrant: a method can acquire the same monitor more than once, and everything will still work.
Multithreading in Java
64
65
This chapter addresses two issues of interest to prospective adopters of Java, namely, what is the performance of Java, and how does it stack up against other comparable programming languages? Lets rst address the performance question and then move on to a brief comparison with other languages.
8.1 Performance
Java has been ported to and run on a variety of hardware platforms executing a variety of operating system software. Test measurement of some simple Java programs on current high-end computer systems such as workstations and high-performance personal computers show results roughly as follows: new Object new C() (class with several methods) o.f() (method f invoked on object o) o.sf() (synchronized method f invoked on object o) 119,000 per second 89,000 per second 590,000 per second 61,500 per second
Thus, we see that creating a new object requires approximately 8.4 sec, creating a new class containing several methods consumes about 11 sec, and invoking a method on an object requires roughly 1.7 sec. While these performance numbers for interpreted bytecodes are usually more than adequate to run interactive graphical end-user applications, situations may arise where higher performance is required. In such cases, the Java bytecodes can be translated on the y (at run time) into machine code for the
66
8
particular CPU on which the application is executing. For those accustomed to the normal design of a compiler and dynamic loader, this is somewhat like putting the nal machine code generator in the dynamic loader. The bytecode format was designed with generating machine codes in mind, so the actual process of generating machine code is generally simple. Reasonably good code is produced: it does automatic register allocation and the compiler does some optimization when it produces the bytecodes. Performance of bytecodes converted to machine code is roughly the same as native C or C++.
67
8
use. And of course when you use C++, you have the perennial fragile superclass issue. Last but denitely not least, the binary distribution problem of compiled code becomes unmanageable in the context of heterogeneous platforms all over the Internet. The Java language environment creates an extremely attractive middle ground between very high-level and portable but slow scripting languages and very low level and fast but non-portable and unreliable compiled languages. The Java language ts somewhere in the middle of this space. In addition to being extremely simple to program, highly portable and architecture neutral, the Java language provides a level of performance thats entirely adequate for all but the most compute-intensive applications.
68
8
Prospective adopters of the Java language need to examine where the Java language ts into the rmament of other languages. Here is a basic comparison chart illustrating the attributes of the Java languagesimple, object-oriented, threaded, and so onas described in the earlier parts of this paper.
Feature exists Feature somewhat exists
Java Simple
SmallTalk
TCL
Perl
Shells
C++
Object Oriented Robust Secure Interpreted Dynamic Portable Neutral Threads Garbage Collection Exceptions
rm erfo
anc
High
Medium
Low
Medium
Low
High
High
From the diagram above, you see that the Java language has a wealth of attributes that can be highly benecial to a wide variety of developers. You can see that Java, Perl, and SmallTalk are comparable programming environments offering the richest set of capabilities for software application developers.
69
8
8.3 A Major Benet of Java: Fast and Fearless Prototyping
Very dynamic languages like Lisp, TCL, and SmallTalk are often used for prototyping. One of the reasons for their success at this is that they are very robustyou dont have to worry about freeing or corrupting memory. Similarly, programmers can be relatively fearless about dealing with memory when programming in Java. The garbage collection system makes the programmers job vastly easier; with the burden of memory management taken off the programmers shoulders, storage allocation errors go away. Another reason commonly given that languages like Lisp, TCL, and SmallTalk are good for prototyping is that they dont require you to pin down decisions early onthese languages are semantically rich. Java has exactly the opposite property: it forces you to make explicit choices. Along with these choices come a lot of assistanceyou can write method invocations and, if you get something wrong, you get told about it at compile time. You dont have to worry about method invocation error.
8.4 Summary
From the discussion above, you can see that the Java language provides high performance, while its interpreted nature makes it the ideal development platform for fast and fearless prototyping. From the previous chapters, youve seen that the Java language is extremely simple and object oriented. The language is secure to survive in the network-based environment. The architecture-neutral and portable aspects of the Java language make it the ideal development language to meet the challenges of distributing dynamically extensible software across networks.
70
71
9
Its a jungle out there, So drink your Java
The HotJava Browser (HotJava) is a new World-Wide Web browser implemented entirely in the Java programming language. HotJava is the rst major end-user application created using the Java programming language and its run-time system as a base. HotJava not only showcases the powerful features of the Java environment, it also provides an ideal platform for distributing Java programs across the Internetthe most complex, distributed, heterogeneous network in the world.HotJava and its rapidly growing Web population of Java language programs called applets (mini-applications), are the most compelling demonstration of the dynamic capabilities of Java. HotJava includes many innovative features and capabilities above and beyond the rst generation of static Web browsers. HotJava is extensible. Its foremost feature is its ability to download Java programs (applets) from anywhere, even across networks, and execute them on the users machine. HotJava builds on the network-browsing techniques established by Mosaic and other Web browsers and expands them by adding dynamic behavior that transforms static documents into dynamic applications.
72
9
HotJava goes far beyond the current generation of statically-oriented Web browsers and brings a much needed measure of interactivity to the concept of the Web browser. It transforms the existing static data display of current generation Web browsers into a new and dynamic viewing system for hypertext, described below. It enables creation and display of animationoriented applications. World-Wide Web content developers can have their applications distributed across the Internet with the click of a button on the users client computer.
73
9
of timely relevance to the World-Wide Web, a user interested in aspects of multimedia law relative to the World-Wide Web can tune in to the home page at www.oikoumene.com/oikoumene for links to intellectual property issues.
Click Link
smtp
nntp
html
http
url
ftp
gif
74
9
9.1.2 The HotJava BrowserA New Concept in Web Browsers
HotJava solves the monolithic approach and moves the focus of interactivity away from the Web server and onto the Web clientthat is, to the computer on which the user is browsing the Web. Because of its basis in the Java system, a HotJava client can dynamically download segments of code that are executed right there on the client machine. Such Java-based applets (miniapplications) can provide full animation, play sound, and generally interact with the user in real time. HotJava removes the static limitations of the Mosaic generation of Web browsers with its ability to add arbitrary behavior to the browser. Using HotJava, you can add applications that range from interactive science experiments in educational material, to games and specialized shopping applications. You can implement interactive advertising, customized newspapers, and a host of application areas that havent even been thought of yet. The capabilities of a Web browser whose behavior can be dynamically updated are open-ended. Furthermore, HotJava provides the means for users to access these applications in a new way. Software migrates transparently across the network as its needed. You dont have to install softwareit comes across the network as you need itperhaps after asking you to pay for it. Content developers for the World-Wide Web dont have to worry about whether or not some special piece of software is installed in a users systemit just gets there automatically. This transparent acquiring of applications frees content developers from the boundaries of the xed media types such as images and text and lets them do whatever theyd like.
75
9
to nd out about things it doesnt understand. The result of this lack of understanding is great exibility and the ability to add new capabilities very easily. new1 smtp nntp url ftp gif
new2
html
HOTJAVA HotJava is the coordinator of a federation of pieces, each with individual responsibility. New pieces can be added at any time. Pieces can be added from across the network, without needing to be concerned with what CPU architecture they were designed for and with reasonable condence that they wont compromise the integrity of a users system.
new3
http
76
9
For example, the following is a snapshot of HotJava in use. Each diagram in the document represents a different sort algorithm. Each algorithm sorts an array of integers. Each horizontal line represents an integer: the length of the line corresponds to the value of the integer and the position of the line in the diagram corresponds to the position of the integer in the array.
In a book or HTML document, the author has to be content with these static illustrations. With HotJava the author can enable the reader to click on the illustrations and see the algorithms animate:
Using these dynamic facilities, content providers can dene new types of data and behavior that meet the needs of their specic audiences, rather than being bound by a xed set of objects.
77
9
the inventor just has to make sure that a copy of its Java code is installed on the server that contains the images they want to publish; they dont have to upgrade all the browsers in the world. HotJava essentially upgrades itself on the y when it sees this new type. The following is an illustration of how HotJava negotiates with a server when it encounters an object of an unknown type:
Browser
User asks for object
Network
Server
request
Time
request
reply
Object Displayed
78
9
The dynamic incorporation of protocols has special signicance to how business is done on the Internet. Many vendors are providing new Web browsers and servers with added capabilities, such as billing and security. These capabilities most often take the form of new protocols. So each vendor comes up with their unique style of security (for example) and sells a server and browser that speak this new protocol. If a user wants to access data on multiple servers on which each has proprietary new protocols, the user needs multiple browsers. This is incredibly clumsy and defeats the synergistic cooperation that makes the World-Wide Web work. Products from Vendor A VATP Server Proprietary Protocol Web Browser
?
Which browser should the poor user run?
VBTP Server
Proprietary Protocol
Web Browser
With HotJava as a base, vendors can produce and sell exactly the piece that is their added value, and integrate smoothly with other vendors, creating a nal result that is seamless and very convenient for the end user. Products from Vendor A VATP Server Proprietary Protocol A B Products from Vendor B VBTP Server Proprietary Protocol Web Browser No problem!
Protocol handlers get installed in a sequence similar to how content handlers get installed: The HotJava Browser is given a reference to an object (a URL). If the handler for that protocol is already loaded, it will be used. If not, the HotJava Browser will search rst the local system and then the system that is the target of the URL.
79
9
9.2 Freedom to Innovate
Innovation on the Internet follows a pattern: initially: someone develops a technology. Theyre free to try all kinds of things since no one else is using the technology and there are no compatibility issues. Slowly, people start using it, and as they do, compatibility and interoperability concerns slow the pace of innovation. The Internet is now in a state where even simple changes that everyone agrees will have signicant merit are very hard to make. User Population
Ability to innovate Time Within a community that uses HotJava, individuals can experiment with new facilities while at the same time preserving compatibility and interoperability. Data can be published in new formats and distributed using new protocols and the implementations of these will be automatically and safely installed. There is no upgrade problem. One need not be inventing new things to need these facilities. Almost all organizations need to be able to adapt to changing requirements. TheHotJava browsers exibility can greatly aid that. As new protocols and data types become important, they can be transparently incorporated.
80
9
Thats all there is to Mosaic. Its essentially very simple. But despite this, the Mosaic program is actually huge since it must contain specialized handlers for all of these data types. Its bundled together into one big monolithic lump. In contrast, HotJava is very small, since all of the protocol and data handlers are brought in from the outside. For example, when it calls the protocol handler, instead of having a table that has a xed list of protocols that it understands, HotJava instead uses this type string to derive a Java language class name. The protocol handler for this type is dynamically linked in if it is missing. They can be linked in from the local system, or they can be linked in from denitions stored on the host where the URL was found, or anywhere else on the net that HotJava suspects might be a good place to look. In a similar fashion, HotJava can dynamically locate and load the code to handle different types of data objects and different ways of viewing them.
9.4 Security
Network security is of paramount importance to Internet users, especially with the exponential growth of Internet commerce. Network-based applications must be able to defend themselves against a veritable gallimaufry of network viruses, worms, Trojan horses, and other forms of intruders. This section discusses the layers of defense provided by Java, the Java run-time system, and the higher-level protocols of HotJava itself. One of the most important technical challenges in building a system like HotJava is making it secure. Downloading, installing,and executing fragments of code importedfrom across the network is potentially an open invitation to all sorts of problems. On the one hand, such a facility provides great power that can be used to achieve very valuable ends; on the other hand, the facility could potentially be subverted to become a breeding ground for computer viruses. The topic of safety is a very broad one and doesnt have a single answer. HotJava has a series of facilities that layer and interlock to provide a fairly high degree of safety.
81
9
When HotJava imports a code fragment, itdoesnt actually know whether or not the code fragment follows Java language rules for safety. As described earlier, imported code fragments are subjected to a series of checks, starting with straightforward tests that the format of the code is correct and ending with a series of consistency checks by the Bytecode Verier.
82
83
Further Reading
10
Ive got a little list. Ive got a little list. Gilbert and SullivanThe Mikado
The Java Programmers Guide Sun Microsystems http://java.sun.com/progGuide/index.html This is the draft version of the Java/HotJava Programmers Guide.
Pitfalls of Object-Oriented Development, by Bruce F. Webster Published by M&T Books. A collection of traps to avoid for people adopting object technology. Recommended readingit alerts you to the problems youre likely to encounter and the solutions for them.
The Design and Evolution of C++, by Bjarne Stroustrop Published by Addison Wesley A detailed history of how we came to be where we are with C++.
84
10
NEXTSTEP Object-Oriented Programming and the Objective C Language. Addison Wesley Publishing Company, Reading, Massachusetts, 1993. The book on Objective C. A good introduction to object-oriented programming concepts.
Discovering Smalltalk. By Wilf Lalonde. Benjamin Cummings, Redwood City, California, 1994. An introduction to Smalltalk.
Eiffel: The Language. By Bertrand Meyer. Prentice-Hall, New York, 1992. An introduction to the Eiffel language, written by its creator.
An Introduction to Object-Oriented Programming. By Timothy Budd. Addison Wesley Publishing Company, Reading, Massachusetts. An introduction to the topic of object-oriented programming, as well as a comparison of C++, Objective C, SmallTalk, and Object Pascal.
Monitors: An Operating System Structuring Concept. By C. A. R. Hoare. Communications of the ACM, volume 17 number 10, 1974. Pages 549-557. The original seminal paper on the concept of monitors as a means to synchronizing multiple concurrent tasks.
85
Sun Microsystems, Inc. 2550 Garcia Avenue Mountain View, CA 94043 415 960-1300 FAX 415 969-9131 For U.S. Sales Ofce locations, call: 800 821-4643 In California: 800 821-4642 Australia: (02) 844 5000 Belgium: 32 2 716 7911 Canada: 416 477-6745 Finland: +358-0-525561 France: (1) 30 67 50 00 Germany: (0) 89-46 00 8-0 Hong Kong: 852 802 4188 Italy: 039 60551 Japan: (03) 5717-5000 Korea: 822-563-8700 Latin America: 415 688-9464 The Netherlands: 033 501234 New Zealand: (04) 499 2344 Nordic Countries: +46 (0) 8 623 90 00 PRC: 861-849 2828 Singapore: 224 3388 Spain: (91) 5551648 Switzerland: (1) 825 71 11 Taiwan: 2-514-0567 UK: 0276 20444 Elsewhere in the world, call Corporate Headquarters: 415 960-1300 Intercontinental Sales: 415 688-9000