|
|
CONTENTS |
|
The greatest challenges and most exciting opportunities for software developers today lie in
We want software that works—consistently,
The problem, historically, has been that the tools for building these applications have
The Java programming language, developed at Sun Microsystems under the guidance of Net luminaries James Gosling and Bill Joy, is designed to be a
Initially, most of the
The
Of the original
Designing NeWS taught Gosling the power of integrating an expressive language with a
The FirstPerson team worked on developing software for information appliances, such as cellular phones and personal digital assistants (PDAs). The goal was to enable the transfer of information and real-time applications over cheap infrared and packet-based networks. Memory and bandwidth limitations dictated small and efficient code. The nature of the applications also demanded they be safe and robust. Gosling and his teammates began programming in C++, but they soon found themselves confounded by a language that was too complex, unwieldy, and
With the foundering of the Apple Newton, it became apparent that the PDA's ship had not yet come in, so Sun shifted FirstPerson's efforts to interactive TV (ITV). The programming language of choice for ITV set-top boxes was to be the near
At that time, Joy and Gosling got together to decide on a new strategy for their language. It was 1993, and the explosion of interest in the Internet, and the Web in particular, presented a new opportunity. Oak was small, robust, architecture-independent, and object-oriented. As it happens, these are also the requirements for a universal, network-savvy programming language. Sun quickly changed focus, and, with a little retooling, Oak became Java.
It would not be overdoing it to say that Java has caught on like
An ongoing lawsuit between Sun and Microsoft over the distribution of Java with Internet Explorer has hampered its deployment on the world's most common operating system—
As we begin looking at the Java architecture, you'll see that much of what is exciting about Java comes from the self-contained, virtual machine environment in which Java applications run. Java has been
Many people see Java as part of a trend toward cheap, Internet-based, "operating system-less" appliances that will
Java is both a compiled and an interpreted language. Java source code is turned into simple binary instructions, much like ordinary microprocessor machine code. However, whereas C or C++ source is refined to native instructions for a particular model of processor, Java source is compiled into a universal format—instructions for a virtual machine .
Compiled Java
byte code
is executed by a Java runtime interpreter. The runtime system
The Java interpreter is relatively lightweight and small; it can be implemented in whatever form is desirable for a particular platform. On most systems, the interpreter is written in a fast, natively compiled language such as C or C++. The interpreter can be run as a separate application, or it can be embedded in another piece of software, such as a web browser.
Put together this means that Java code is implicitly portable. The same Java application byte code can run on any platform that provides a Java runtime environment, as shown in Figure 1-1. You don't have to produce alternative versions of your application for different platforms, and you don't have to distribute source code to end users.
The fundamental unit of Java code is the
class
. As in other object-oriented languages, classes are application
In addition to the platform-specific runtime system, Java has a number of fundamental classes that contain
Historically, interpreters have been
This is an often misunderstood point among those who want to compare language performance. There is only one intrinsic performance hit that compiled Java code suffers at runtime for the sake of security and virtual machine design—array bounds checking. Everything else can be optimized down to native code just as it can with a statically compiled language. Going beyond that, the Java language includes more structural information than many other languages, providing more room for optimizations. Also remember that these optimization can be made at runtime, taking into account the actual application characteristics. What can be done at compile time that can't be done better at runtime? Well, there is a trade-off: time.
The problem with a traditional JIT compilation is that optimizing code takes time and is extremely important for good performance on modern computer hardware. So a JIT compiler can produce decent results but may not be able to take the time necessary to do a good job of optimization up front. Sun's compiler technology, called HotSpot, uses a trick called
adaptive compilation
to solve this problem. If you look at what programs actually spend their time doing, it turns out that they
To take advantage of this fact, HotSpot starts out as a normal Java byte code interpreter, but with a difference: it measures (profiles) the code as it is executing, to see what
The technology for doing this is complex, but the idea is
Java is a new language, but it draws on many years of programming experience with other languages in its choice of features. Much can be said in comparing and contrasting Java with other languages. There are at least three pillars necessary to support a universal language for network programming today: portability, speed, and security. Figure 1-2 shows how Java
You may have
The surface-level similarities to these languages are worth noting, however. Java borrows heavily from C and C++ syntax, so you'll see lots of familiar language constructs, including an
C has been successful because it provides a reasonably featureful programming environment, with high performance and an acceptable degree of portability. Java also
In the early days, before JIT and adaptive compilation, Java was considerably slower than compiled languages. But as we described in the previous section, Java's performance is now comparable to C or C++ for equivalent tasks.
Scripting languages, such as Perl, Python, and Ruby, are becoming very popular, and for good reason. There's no reason a scripting language can't be suitable for safe, networked applications. But most scripting languages are not designed for serious, large-scale programming. The attraction to scripting languages is that they are dynamic; they are powerful tools for rapid prototyping. Some scripting languages such as Perl also provide powerful tools for text-processing tasks that more general-purpose languages find unwieldy. Scripting languages are also highly portable.
One problem with scripting languages, however, is that they are rather casual about program structure and data typing. Most scripting languages (with a hesitant exception for Perl 5.0 and Python) are not object-oriented. They also have vastly simplified type systems and
Java offers some of the essential advantages of a scripting language, along with the added benefits of a lower-level language. Java 1.4 adds a complete Regular Expression API that makes it as powerful as Perl for working with text.
However, don't confuse Java with JavaScript! JavaScript is an object-based scripting language being developed by Netscape and others. It serves as a glue and an "in the document" language for dynamic, interactive HTML-based applications. JavaScript takes its name from its intended integration with Java. You can currently interact with Java applets embedded in HTML using JavaScript. There have been a few portable implementations of JavaScript that would promote it to the level of a general scripting language. For more information on JavaScript, check out JavaScript: The Definitive Guide by David Flanagan (O'Reilly & Associates).
Incremental development with object-oriented components, combined with Java's simplicity, make it possible to develop applications rapidly and change them easily. Many studies have found that development in Java is 10 times faster than in C or C++, strictly based on language features. Java also comes with a large base of core classes for common tasks such as building GUIs and doing network communications. But along with these features, Java has the scalability and software-engineering advantages of more static languages. It provides a safe structure on which to build higher-level frameworks (and even other languages).
As we've already said, Java is similar in design to languages such as Smalltalk and Lisp. However, these languages are currently used mostly as research vehicles, rather than for developing large-scale systems. One reason is that they never developed a standard portable binding to operating-system services, such as the C standard library or the Java core classes. Smalltalk is compiled to an interpreted bytecode format, and it can be dynamically compiled to native code on the fly, just like Java. But Java
Throughout the rest of this chapter, we'll present a bird's-eye view of the Java language. We'll explain what's new and what's not-so-new about Java, how it
You have no doubt heard a lot about the fact that Java is designed to be a safe language. But what do we mean by safe? Safe from what or whom? The security features that
In this section, though, we'll look at some general features of the Java programming language. Perhaps more important than the specific security features, although often overlooked in the security din, is the safety that Java provides by addressing common design and programming problems. Java is intended to be as safe as possible from the simple mistakes we make
Java is parsimonious in its features; simplicity rules. Unlike C++, Java doesn't allow programmer-defined operator overloading. (The string concatenation operator + is the only system-defined, overloaded operator in Java.). Java doesn't have a preprocessor, so it doesn't have macros, #define statements, or conditional source compilation. These constructs exist in other languages primarily to support platform dependencies, so in that sense they should not be needed in Java. Conditional compilation is also commonly used for debugging purposes. Debugging code can be included directly in your Java source code by making it conditional on a constant (we'll talk about those in Chapter 4). The Java compiler is smart enough to remove this code when it determines that it won't be called.
Java provides a
Java
One attribute of a language is the kind of type checking it uses. Generally, when we categorize a language as static or dynamic, we are referring to the amount of information about variable types that is known at compile time versus what is determined while the application is running.
In a strictly statically typed language such as C or C++, data types are etched in stone when the source code is compiled. The compiler benefits from having enough information to enforce usage rules, so that it can catch many kinds of errors before the code is executed, such as storing a floating-point value in an integer variable. The code then doesn't require runtime type checking, so it can be compiled to be small and fast. But statically typed languages are
In contrast, a dynamic language such as Smalltalk or Lisp has a runtime system that manages the types of objects and performs necessary type checking while an application is executing. These kinds of languages allow for more complex behavior and are in many respects more powerful. However, they are also generally slower, less safe, and harder to debug.
The differences in languages have been likened to the differences among kinds of automobiles.
[1]
Statically typed languages such as C++ are analogous to a sports car—reasonably safe and fast—but useful only if you're driving on a
Another attribute of a language is the way it binds method calls to their definitions. In an language such as C or C++, the definitions of methods are normally bound at compile time, unless the programmer specifies
Java provides some of the benefits of both C++ and Smalltalk; it's a statically typed, late-binding language. Every object in Java has a well-defined type that is known at compile time. This means the Java compiler can do the same kind of static type checking and usage analysis as C++. As a result, you can't assign an object to the wrong type of variable or call nonexistent methods on an object. The Java compiler goes even further and
However, Java is fully runtime-typed as well. The Java runtime system keeps track of all objects and makes it possible to determine their types and relationships during execution. This means you can inspect an object at runtime to determine what it is. Unlike C or C++, casts from one type of object to another are checked by the runtime system, and it's possible to use new kinds of dynamically loaded objects with a level of type safety. And since Java is a late-binding language, all methods are like virtual methods in C++. This means that it's possible for a subclass to override methods in its superclass, even a subclass loaded at runtime.
Java carries all data-type and method-signature information with it from its source code to its compiled bytecode form. This means that Java classes can be developed incrementally. Your own Java classes can also be used safely with classes from other sources your compiler has never seen. In other words, you can write new code that references binary class files, without losing the type safety you gain from having the source code.
A common irritation with C++ is the "fragile base class" problem. In C++, the implementation of a base class can be effectively frozen by the fact that it has many derived classes; changing the base class may require recompilation of the derived classes. This is an
Some of the most important differences between Java and C or C++ involve how Java manages memory. Java eliminates ad hoc pointers and adds garbage collection and true arrays to the language. These features eliminate many otherwise insurmountable problems with safety, portability, and optimization.
Garbage collection alone should save countless programmers from the single largest source of programming errors in C or C++: explicit memory allocation and deallocation. In addition to maintaining objects in memory, the Java runtime system keeps track of all references to those objects. When an object is no longer in use, Java automatically
Java uses a sophisticated garbage collector that runs intermittently in the background, which means that most garbage collecting takes place during idle times, between I/O pauses, mouse clicks, or keyboard hits. Next-generation runtime systems such as HotSpot have even more advanced garbage collection that can even differentiate the usage patterns of objects (such as short-lived versus long-lived) and optimize their collection. Once you get used to garbage collection, you won't go back. Being able to write air-tight C code that juggles memory without dropping any on the floor is an important skill, but once you become addicted to Java, you can reallocate some of those brain
You may hear people say that Java doesn't have pointers. Strictly speaking, this statement is true, but it's also misleading. What Java provides are references—a safe kind of pointer—and Java is rife with them. A reference is a strongly typed handle for an object. All objects in Java, with the exception of primitive numeric types, are accessed through references. If necessary, you can use references to build all the normal kinds of data structures you're accustomed to building with pointers, such as linked lists, trees, and so forth. The only difference is that with references you have to do so in a type-safe way.
Another important difference between a reference and a pointer is that you can't do pointer arithmetic with references (they can point only to specific objects or elements of an array). A reference is an atomic thing; you can't manipulate the value of a reference except by assigning it to an object. References are passed by value, and you can't reference an object through more than a single level of indirection. The protection of references is one of the most fundamental aspects of Java security. It means that Java code has to play by the rules; it can't peek into places it shouldn't.
Unlike C or C++ pointers, Java references can point only to class types. There are no pointers to methods. People sometimes complain about this missing feature, but you will find that tasks that call for pointers to methods can be accomplished more cleanly using interfaces and adapter classes instead. We should also mention that Java has a sophisticated "reflection" API that actually allows you to reference and invoke individual methods. However this is not the normal way of doing things. We discuss reflection in Chapter 6.
Finally, arrays in Java are true, first-class objects. They can be dynamically allocated and assigned like other objects. Arrays know their own
Java's roots are in networked devices and embedded systems. For these applications, it's important to have robust and intelligent error management. Java has a powerful exception-handling mechanism, somewhat like that in
When an exception occurs, it causes the flow of program execution to be transferred to a predesignated "
Applications today require a high degree of parallelism. Even a very single-minded application can have a complex user interface—which requires concurrent activities. As machines get faster, users become more sensitive to waiting for unrelated tasks that seize control of their time. Threads provide efficient multiprocessing and distribution of tasks for both client and server applications. Java makes threads easy to use because support for them is built into the language.
Concurrency is nice, but there's more to programming with threads than just performing multiple tasks
Learning to program with threads is an important part of learning to program in Java. See Chapter 8 for a discussion of this topic. For complete coverage of threads, refer to Java Threads by Scott Oaks and Henry Wong (O'Reilly).
At the
Within a package, a class is either
It's one thing to create a language that prevents you from shooting yourself in the foot; it's quite another to create one that prevents others from shooting you in the
Encapsulation is a technique for hiding data and behavior within a class; it's an important part of object-oriented design. It helps you write clean, modular software. In most languages, however, the visibility of data items is simply part of the relationship between the programmer and the compiler. It's a matter of semantics, not an assertion about the actual security of the data in the context of the running program's environment.
When Bjarne Stroustrup chose the keyword
private
to
// C++ code
class Finances {
private:
char creditCardNumber[16];
...
};
main( ) {
Finances finances;
// Forge a pointer to peek inside the class
char *cardno = (char *)&finances;
printf("Card Number = %s\n", cardno);
}
In this little C++ drama, we have written some code that
In Visual BASIC, it's also possible to compromise the system by
If a Java application is to dynamically download code from an untrusted source on the Internet and run it
At the outside, application-level security decisions are made by a security manager. A security manager controls access to system resources such as the filesystem, network ports, and the windowing environment. A security manager relies on the ability of a class loader to protect basic system classes. A class loader handles loading classes from the network. At the inner level, all system security ultimately rests on the Java verifier, which
The Java bytecode verifier is a fixed part of the Java runtime system. Class loaders and security managers (or
security policies
to be more precise), however, are components that may be implemented differently by different applications that load byte code, such as applet
Java's first line of defense is the bytecode verifier . The verifier reads byte code before it is run and makes sure it is well-behaved and obeys the basic rules of the Java language. A trusted Java compiler won't produce code that does otherwise. However, it's possible for a mischievous person to deliberately assemble bad code. It's the verifier's job to detect this.
Once code has been verified, it's considered safe from certain inadvertent or malicious errors. For example,
You might be wondering, isn't this kind of safety implicit in lots of interpreted languages? Well, while it's true that you shouldn't be able to corrupt the interpreter with
By comparison, Java byte code is a relatively light, low-level instruction set. The ability to statically verify the Java byte code before execution lets the Java interpreter run at full speed with full safety, without expensive runtime checks.
The verifier is a type of mathematical "theorem prover." It steps through the Java byte code and applies simple, inductive rules to determine certain aspects of how the byte code will behave. This kind of analysis is possible because compiled Java byte code contains a lot more type information than the object code of other languages of this kind. The byte code also has to obey a few extra rules that simplify its behavior. First, most bytecode instructions
Second, the type of object resulting from any operation is always known in advance. There are no bytecode operations that
Because an operation always produces a known type, by looking at the starting state it's possible to determine the types of all items on the stack and in local variables at any point in the future. The collection of all this type information at any given time is called the type state of the stack; this is what Java tries to analyze before it runs an application. Java doesn't know anything about the actual values of stack and variable items at this time, just what kind of items they are. However, this is enough information to enforce the security rules and to ensure that objects are not manipulated illegally.
To make it
Java adds a second layer of security with a class loader . A class loader is responsible for bringing the byte code for one or more Java classes into the interpreter. Every application that loads classes from the network must use a class loader to handle this task.
After a class has been loaded and passed through the verifier, it remains associated with its class loader. As a result, classes are effectively partitioned into separate namespaces based on their origin. When a loaded class references another class name, the location of the new class is provided by the original class loader. This means that classes retrieved from a specific source can be restricted to interact only with other classes retrieved from that same location. For example, a Java-enabled web browser can use a class loader to build a separate space for all the classes loaded from a given URL.
The search for classes always begins with the built-in Java system classes. These classes are loaded from the locations specified by the Java interpreter's classpath (see Chapter 3). Classes in the classpath are loaded by the system only once and can't be
Finally, a security manager is responsible for making application-level security decisions. A security manager is an object that can be installed by an application to restrict access to system resources. The security manager is consulted every time the application tries to access items such as the filesystem, network ports, external processes, and the windowing environment; the security manager can allow or deny the request.
A security manager is most useful for applications that run untrusted code as part of their normal operation. Since a Java-enabled web browser can run applets that may be retrieved from untrusted sources on the Net, such a browser needs to install a security manager as one of its first actions. This security manager then restricts the kinds of access allowed after that point. This lets the application impose an effective level of trust before running an arbitrary piece of code. And once a security manager is installed, it can't be replaced.
In recent versions of Java, the security manager works in conjunction with an access controller that lets you implement security policies by editing a file. Access policies can be as simple or complex as a particular application
The integrity of a security manager is based on the protection afforded by the lower levels of the Java security model. Without the guarantees provided by the verifier and the class loader, high-level assertions about the safety of system resources are meaningless. The safety provided by the Java bytecode verifier means that the interpreter can't be corrupted or subverted and that Java code has to use components as they are intended. This, in
There's a fine line between having enough power to do something useful and having all the power to do anything you want. Java provides the foundation for a secure environment in which untrusted code can be quarantined, managed, and safely executed. However, unless you are content with keeping that code in a little black box and running it just for its own benefit, you will have to grant it access to at least some system resources so that it can be useful. Every kind of access carries with it certain risks and benefits. For example, in the web browser environment, the advantages of granting an untrusted (unknown) applet access to your windowing system are that it can display information and let you interact in a useful way. The associated risks are that the applet may instead display something worthless, annoying, or offensive. Since most people can accept that level of risk, graphical applets and the Web in general are possible.
At one extreme, the simple act of running an application gives it a resource—computation time—that it may put to good use or burned frivolously. It's difficult to prevent an untrusted application from wasting your time or even attempting a "denial of service" attack. At the other extreme, a powerful, trusted application may justifiably deserve access to all sorts of system resources (e.g., the filesystem, process creation, network interfaces); a malicious application could wreak havoc with these resources. The message here is that important and sometimes complex security issues have to be addressed.
In some situations, it may be acceptable to simply ask the user to "okay"
Making decisions about what is dangerous and what is not can be difficult. Even ostensibly harmless access, such as displaying a window, can become a threat when paired with the ability of an untrusted application to communicate from your host. The Java Security Manager provides an option to flag windows created by an untrusted application with a special, recognizable border to prevent it from impersonating another application and perhaps tricking you into revealing your password or your secret recipe collection. There is also a grey area, in which an application can do
Web browsers that run Java applets, such as Sun's HotJava, start by defining a few rules and some coarse levels of security that restrict where applets may come from and what system resources they may access. These rules are sufficient to keep the waving Duke applet from clutching your password file, but they aren't sufficient for applications you'd like to trust with sensitive information. To fully exploit the power of Java, we need to have some nontechnical basis on which to make reasonable decisions about what a program can be allowed to do. This nontechnical basis is trust; basically, you trust certain entities not to do anything that's
This doesn't mean that there isn't a technical aspect to the problem of trust. Trusting your local bank when you walk up to the ATM means one thing; trusting some web page that claims to come from your local bank means something else entirely. It would be very difficult to impersonate the ATM two blocks down the street (though it has been known to happen), but, depending on your position on the Net, it's not all that difficult to impersonate a web site or to intercept data coming from a
That's where cryptography comes in. Digital signatures, together with certificates, are techniques for verifying that data truly comes from the source it claims to have come from and hasn't been modified en route. If the Bank of Boofa signs its
The application-level safety features of Java make it possible to develop new kinds of applications that were not feasible before. A web browser that uses the Java runtime system can
In addition to applets, a more recent model for Internet downloadable application content is Java Web Start. The Web Start API allows your web browser to install applications locally, with stringent security still enforced by the Java runtime system. This system can also automatically update the software when it is used. We'll discuss this more in Chapter 22.
The
As far as the web browser model is
A Java applet is a compiled Java program,
An applet has a four-part life cycle. When an applet is initially loaded by a web browser, it's asked to initialize itself. The applet is then informed each time it's displayed and each time it's no longer visible to the user. Finally, the applet is told when it's no longer needed, so that it can clean up after itself. During its lifetime, an applet may start and suspend itself, do work, communicate with other applications, and interact with the web browser.
Applets are autonomous programs, but they are confined within the walls of a web browser or applet viewer, and have to play by its rules. We'll be discussing the details of what applets can and can't do as we explore features of the Java language. However, under the most conservative security policies, an applet can interact only with the user and can communicate over the network only with the host from which it originated. Other types of activities, such as accessing files or interacting directly with outside applications, are typically prevented by the security manager that is part of the web browser or applet viewer. But aside from these restrictions, there is no fundamental difference between a Java applet and a standalone Java application.
When it was first released, Java quickly achieved a reputation for multimedia capabilities. Frankly, this wasn't really deserved. At that point, Java provided facilities for doing simple animations and playing audio (which was leaps and bounds beyond static web pages). You could animate and play audio simultaneously, though you couldn't synchronize the two. Still, this was a significant advance for the Web, and people thought it was pretty impressive.
Java's multimedia capabilities have now taken shape. Java now has CD-quality sound, 3D animation, media players that synchronize audio and video, speech synthesis and recognition, and more. The Java Media Framework now supports most common audio and video file formats; the Java Sound API (part of the core classes) can record sound from a computer's microphone.
For many years, people have been using integrated development environments (
For visual development environments to work well, you need to be able to create reusable software components. That's what the JavaBeans architecture is all about: it defines a way to package software as reusable building blocks. A graphical development tool can figure out a component's capabilities, customize the component, and connect it to other components to build applications. JavaBeans takes the idea of graphical development a step further. JavaBeans components, called Beans, aren't limited to visible, user interface components: you can have Beans that are entirely invisible and whose job is purely computational. For example, you can have a Bean that does database access; you can connect this to a Bean that lets the user request information from the database; and you can use another Bean to display the result. You can also have a set of Beans that implement the functions in a mathematical library; you can then do numerical analysis by connecting different functions to each other. In either case, you can create programs without writing a single line of code using Beans from a variety of sources. Granted, someone would have to write the Beans in the first place, but that's a different kind of task.
The JavaBeans APIs are a set of naming and design patterns that work with other Java capabilities—
reflection
and
serialization
—to allow tools to discover the capabilities of components and hook them together. The JavaBeans standard also specifies ways for individual beans to provide explicit information for these builder tools, including user friendly
Visual development tools that support JavaBeans include Sun's Forte for Java—a commercial product that is also available in an open source version called NetBeans (http://www.netbeans.org/), IBM's VisualAge, Inprise's JBuilder (http://www.inprise.com), and WebGain's Visual Cafe (http://www.webgain.com). By using a "bridge," JavaBeans can also function inside ActiveX components, which are used by many IDEs.
Java was introduced to the world through the web browser and the Java applet API. However, Java is more than just a tool for building multimedia applications. Java is a powerful, general-purpose programming language that just happens to be safe and architecture-independent. Standalone Java applications are not subject to the restrictions placed on applets; they can perform the same jobs as do programs written in languages such as C and C++.
Any software that implements the Java runtime system can run Java applications. Applications written in Java can be large or small, standalone or component-like, as in other languages. Java applets are different from other Java applications only in that they expect to be managed by a larger application. They are also normally considered untrusted code. In this book, we will build examples of both applets and standalone Java applications. With the exception of the few things untrusted applets can't do, such as access files, all the tools we examine in this book apply to both applets and standalone Java applications.
With everything that's going on, it's hard to keep track of what's available now, what's
Java 1.0 provided the basic framework for Java development: the language itself plus packages that let you write applets and simple applications. Although 1.0 is officially obsolete, there are still a lot of applets in existence that conform to its API.
Java 1.1 superseded 1.0, incorporating major improvements in the AWT package (Java's original GUI facility), a new event pattern, new language facilities such as reflection and inner classes, and many other critical features. Java 1.1 remains important, because it is supported natively by most versions of Netscape Navigator and Microsoft Internet Explorer browsers. For various political reasons, the future of the browser world has been frozen in this condition for many years; to execute applets using any features of Java after Version 1.1, you need to use the Java Plug-in, which allows Netscape and IE to use an up-to-date Java implementation. The latest version of Netscape (6.x) also supports Java 1.3.
Java 1.2, dubbed "Java 2" by Sun, was a major release in December 1998. It provided many improvements and additions,
Java 1.3, released in early 2000, added minor features but was primarily focused on performance. With Version 1.3, Java got significantly faster on many platforms and Swing got many bug fixes. In this timeframe, Java enterprise APIs such as Servlets and Enterprise JavaBeans also matured.
This book includes all the latest and greatest improvements through the final release of Java 1.4. This release provides many important and long-awaited features including language assertions, regular expressions, preferences and logging APIs, a new I/O system for high-volume applications, standard support for XML, fundamental improvements in AWT and Swing, and a greatly matured Java Servlets API for web applications.
Here's a brief overview of the most important features of the current core Java API:
A general facility for interacting with databases. (Introduced in Java 1.1.)
Java's distributed objects system. RMI lets you call methods on objects hosted by a server running somewhere else on the network. (Introduced in Java 1.1.)
A facility for controlling access to system resources, combined with a uniform interface to cryptography. Java Security is the basis for signed classes, which were discussed earlier.
A catch-all for a number of new features, including the Swing user interface components; "pluggable look-and-feel," which means the ability of the user interface to adapt itself to the "look-and-feel" of the platform you're using; drag and drop; and accessibility, which means the ability to integrate with special software and hardware for people with
Part of JFC; enables
The ability to write programs that adapt themselves to the language the user wants to use; the program automatically displays text in the appropriate language. (Introduced in Java 1.1.)
A general service for looking up resources. JNDI unifies access to directory services such as LDAP, Novell's NDS, and others.
The following "standard extension" APIs aren't part of the core Java distribution; you may have to download them separately.
A uniform API for writing email software.
A facility for developing applications with 3D graphics.
Another catch-all that includes Java 2D, Java 3D, the Java Media Framework (a framework for coordinating the display of many different kinds of media), Java Speech (for speech recognition and synthesis), Java Sound (high-quality audio), Java TV (for interactive television and similar applications), and others.
A facility that lets you write server-side web applications in Java.
Actual implementations of cryptographic algorithms. (This package was separated from Java Security for legal reasons.)
A facility for writing help systems and incorporating them in Java programs.
A component architecture for building distributed server-side applications.
An extremely interesting catch-all that is designed to enable massively distributed computing, including computing on common household appliances. In a few years, your stereo may be able to execute Java programs.
A version of Java for very small (i.e., credit card-
In this book, we'll try to give you a taste of as many features as possible;
You can think of the first four years of Java development as a "big bang," followed by an "inflationary" phase as Sun added new features and improved old features, at an incredible rate. Things seem to be
Probably the most exciting front for Java now is in the area of small devices. The Java "Java 2 Micro Edition" or J2ME is a subset of Java designed to fit on devices with limited capabilities. The reference platform for the J2ME architecture is the Palm PDA. Java is also now beginning to ship in cell phones, allowing downloadable applications and media.
You have several choices for Java development environments and runtime systems. Sun's Java software development kit is available for Solaris, Linux, and Windows. Visit Sun's Java web site at http://java.sun.com for more information about obtaining the latest Java SDK (Version 1.4 is included on the
Most versions of Netscape Navigator and Microsoft Internet Explorer come with their own Java runtime system that runs Java applets and supports Java 1.1. Neither supports later Java releases at present, although Netscape 6 does support Java 1.3. To ameliorate the problem in general, Sun has released a Java Plug-in that allows you to specify and install the latest versions of Java; it is distributed with the Java development kit (SDK) and runtime systems (JRE) for Windows.
[1] The credit for the car analogy goes to Marshall P. Cline, author of the C++ FAQ.
[2] You may have seen
reports about various security flaws in Java. While these weaknesses are real, it's important to realize that they have been found in the various implementations of components, namely Sun's, Netscape's, and Microsoft's Java virtual machines, not in the basic security model itself. One of the reasons Sun has released the source code for Java is toencourage people to search for weaknesses so that they can be removed.[3] The implications of this rule are of interest mainly to compiler writers. The rule means that Java byte code can't perform certain types of iterative actions within a single frame of execution. A common example would be looping and pushing values onto the stack. This is not allowed because the
path of execution would return to the top of the loop with apotentially different type state on each pass, and there is no way that a static analysis of the code can determine whether it obeys the security rules. This restriction makes it possible for the verifier to trace each branch of the code just once and still know the type state at all points. Thus, the verifier can ensure that instruction types and stack value types alwayscorrespond , without actually following the execution of the code. For a more thorough explanation of all this, see The Java Virtual Machine by Jon Meyer and Troy Downing (O'Reilly).
|
|
CONTENTS |
|