image

CHAPTER

1

Introduction to Java

imageince its release in 1996, Java has been a popular language among developers worldwide. As of this writing, official sources (namely Oracle) claim that there are about 9 million active Java developers worldwide. Java has been widely accepted as the language of choice for developing almost every kind of application, ranging from small web-based Java applets to large distributed enterprise applications. You will also find Java being used in small-embedded devices as well as very large mission-critical applications. You will find Java being used in colleges by students doing their projects, in industries by developers for their commercial projects, in government for their scalable applications, in banks for their time-critical reliable applications, and in militaries for their robust mission-critical applications. You will find that Java is used in almost every corner of the world.

So what is it that has made Java so popular? Is Java merely a programming language like Pascal, C, or C++? Is it a tool for creating applications of various sizes and complexities? Is it a platform for running applications right from embedded to enterprise level? In this chapter, I will try to answer these questions and many more. You will learn what is so special about Java that has made it so popular. In particular you will learn the following:

image  Why Java was created
image  What Java is
image  The features of Java
image  Java’s evolution

Why Java?

Java was publicly released in 1996. At that time, C++ substantially dominated the market and was widely used for creating many kinds of software applications. With C++ having such a stronghold in the market, almost nobody would have thought of bringing a new programming language into the world of computing—but Sun Microsystems did. When they came out with Java, they had specific reasons for developing a new language at that time. One of the primary goals for developing a new language was the need for an appropriate language in developing embedded device applications.

There were many issues with then existing languages. C++ has always been known as “resource hungry.” C++ developers are required to manage memory themselves. A typical “Hello World” program written in C++ with, say, Microsoft’s Visual Studio requires several megabytes of memory to run the code. Though C++ generates highly optimized code, the runtime requirements to run it are typically very high. This was also true for other development and runtime systems available in the market at that time, such as Borland C++ and Turbo Pascal—thus the strong need for a language that would generate small code and use a runtime environment that would not occupy a lot of memory space on the target device.

Programming for embedded devices also demands portability, and these devices typically use a wide variety of CPUs and different architectures. Each architecture made C++ applications behave differently and typically needed to be rewritten for new devices. The complexity of managing multiple build environments and codebases was the biggest challenge in supporting multidevice development. Java was an attempt to create a higher-level language that eliminated these problems— and it largely succeeded in its attempt. It eliminated the multidevice development problems with the introduction of a virtual machine (VM) and portable bytecode architecture. Sun Microsystems aptly came up with the marketing slogan “Write Once, Run Anywhere.”

So What Is Java?

The previous section described why Java was created. It started out as a programming language that had a lot of similarities to C++ and Smalltalk, and it was designed to appeal to C++ developers. Java was created as a simpler, higher-level language that removes complexities such as memory management and security and relegates them to tasks managed by the VM.

image

NOTE

Today, Java is much more than a simple programming language. It is a platform as well as a development and runtime environment. By the end of this chapter, you will understand what Java is from the perspective of today’s computing environment.

The creators of Java wanted to establish an easy migration path for developers, most of whom were quite strong in C++ at that time. Although Java had lots of similarities to C++, such as being an object-oriented language, the creators eliminated the drawbacks and not commonly used features of C++ from their new language. This made Java not only small, but offered several side benefits, such as making it more robust, simple, and portable.

Before we cover Java’s language features, let’s look at its architecture and the concept of a “virtual machine.”

Java Virtual Machine

A Java compiler translates the Java source program into what is known as bytecode, which is similar to the OBJ code generated by a C++ compiler or any other language compiler. The only difference is that most of these compilers generate the object code for a real CPU, whereas the bytecode generated by a Java compiler consists of the instructions for a “pseudo CPU.” In other words, whereas C++ OBJ code consists of the instruction set for, say, an Intel 80x86 CPU or Motorola 68xxx CPU, or maybe even a SPARC workstation, Java bytecode represents an instruction set for a CPU that does not exist in reality. What Sun Microsystems did was to create a virtual CPU in memory, and they designed an instruction set for this virtual CPU, which itself is emulated in memory at runtime.

A Java virtual machine (JVM) emulates the aforementioned virtual CPU. The JVM provides the runtime environment for a Java executable (bytecode). It also provides a bytecode interpreter and a verifier that confirms the bytecode’s validity before translating and running it on a real CPU. In addition, it has several more modules for security, memory and thread management, and other purposes. A JVM is essentially a machine (as its name suggests) that is capable of running a Java executable. The JVM and its essential components that are relevant to us at this time are shown in Figure 1-1.

image

FIGURE 1-1.   Java Virtual Machine

The Java compiler stores the generated bytecode in a file with the extension .class. Your program will also use several .class files supplied by the Java Development Kit (JDK). The class loader in JVM loads these .class files in memory. Along with your .class files, JVM also loads other library files required by your application at the runtime. The JVM subjects the loaded classes to verification to ensure that they do not contain any undefined instructions for the pseudo CPU. The internal .class files need not go through such verifications. If the bytecode of your application program contains an invalid instruction, the JVM rejects its execution and unloads it from memory. After the code is verified, a built-in interpreter converts it to machine code. Now, the code is handed over to the execution unit to be run on the host.

Based on this understanding of Java’s architecture, you will now be able to appreciate its features.

Features of Java

Java offers several benefits over other programming languages. It is small and simple, and it is object oriented. It may be treated as both a compiled and interpreted language. The executables generated by the Java compiler run on any platform that provides a JVM. The Java platform itself is robust and secure. Like many other languages, it supports multithreading, albeit in a much simpler form. And lastly, like a few other languages, it is dynamic in nature. We will now look at each of these features in more detail.

Small

As stated previously, the main motive behind creating Java was to develop a language for embedded systems programming. The executable code generated by Java is very small; typically, a Hello World application translates into just a few bytes. Compare this with similar code generated by a C++ compiler, which is easily a few kilobytes in size and additionally requires lot of memory for its runtime. The runtime environment required to run Java compiled code typically takes less than 1MB of memory space. Again, contrast this with the runtime required to run a C++ application, which involves not only hundreds of megabytes of code embedded in MFC (Microsoft Foundation Classes) or OWL (Borland’s Object Windowing Library) but also requires a sophisticated operating system and hardware to deploy it. Although this was true for both stand-alone and GUI-based applications during the previous decade, Microsoft’s current .NET platform provides an architecture similar to Java and its executables, and runtime environment requirements are comparable to those of Java’s.

image

NOTE

Both MFC and OWL were the popular libraries at the time Java was introduced.

Simple

Being object oriented, Java is simple to learn. It has often been said that people who never learned procedure-oriented languages such as C and Pascal will always leap-frog those who have when it comes to learning an object-oriented language. Those who have learned procedural-oriented languages typically find the migration to object-oriented languages difficult because it may require some undoing of what they have learned previously. Java is simple enough to be introduced as a first programming language in any computer science curriculums.

Object Oriented

The next important feature of Java is that it is object oriented. C++, which originated from C, allows global variable declarations, which means that the variables can be declared outside the scope of any object—to be more precise, outside of any class definition. This violates the rules of encapsulation—one of the important features of an object-oriented language (the features of object-oriented programming are covered in Chapter 3). Java does not allow global declarations. Similarly, in Java, there are no structures and unions like in C and C++ that break the rules of object orientation by making all their members public by default. The absence of these features in the Java language has made it a better object-oriented language.

In Java, the entire code consists of only fully encapsulated classes. You’re probably wondering about the primitive data types. Are these, too, represented as objects in Java? To maintain efficiency, Java declares primitive data types as non-objects; however, it also provides wrapper classes for these primitive data types should you prefer to use objects holding the primitive data type items.

Compiled and Interpreted

Here lies the major difference between Java and languages such as C++, Pascal, and many others. These languages compile their source program into object code (an .obj file). The linker converts the generated object code into an executable (.exe file) by combining object code with the desired libraries. When you run the EXE, the loader in the operating system loads the executable code in memory, resolves the function references with the absolute memory addresses, and executes the code.

Compiling and running a Java program differs substantially from the preceding procedure. As explained earlier, a Java compiler translates the Java source program into what is known as bytecode, which is the set of instructions for a virtual CPU. No linker process is involved when you create an executable from a Java source program. In fact, the only executable that is created from a Java source program is the bytecode. So how does this bytecode run on a real CPU? When you run a Java executable (bytecode) on your machine, an interpreter converts each bytecode instruction into a real CPU instruction. This instruction then executes on the real CPU, so compiling and running a Java program involves both compilation and interpretation processes. Thus, Java is considered both compiled and interpreted.

As Java bytecode is interpreted into machine language instructions at runtime, Java code execution suffers in performance. To overcome this performance limitation, most JVMs implement a number of code optimization techniques, one of which is the use of a Just-in-Time (JIT) compiler that translates the bytecode into machine language code before the real CPU begins the program execution. Obviously, the JIT compiler cannot perform as many optimizations as an offline compiler such as the C++ compiler, because it has to translate the bytecode into machine language code in real time. If the JIT compiler were to attempt to do so, it would take a long time to start the program after the user fires it up from the command line. You have to consider the tradeoff between startup time and throughput. VMs employ a variety of optimization techniques these days. Most of them can be tuned to prefer startup over throughput, or how quickly they adapt the optimizations. There’s a whole body of expertise on tuning VMs for performance, and for many apps, the Java version is as quick as (and sometimes quicker than) the C++ counterpart.

Platform Independent

A major benefit that is derived out of the introduction of a JVM is the resulting platform independence for a Java executable. As seen in the previous section, the JVM provides a runtime environment for Java executables. Also, you have seen that the JVM is a software program that runs on a target environment. Thus, as long as you have a JVM for a desired machine, your compiled Java code (bytecode) will run on that machine without requiring any changes in the binary or the source program. This way, a Java program becomes platform independent at the binary level. Any compiled Java application would run on any platform without any changes as long as the target platform provides a Java virtual machine. This turned out to be a great boon for application developers who could now easily create a portable application that would run on several operating systems without any code modifications. In the days before the introduction of Java, creating portable applications was a painstaking task for many developers. These developers lost important revenue if they were unable to port their popular applications onto other platforms—and those who were able still had to rewrite them for new devices. The platform independence of a Java application is illustrated in Figure 1-2.

image

FIGURE 1-2.   Demonstrating Java Portability

As seen in Figure 1-2, a Java compiler compiles the given source program into machine-independent bytecode. Each of the three machines shown in the figure run a different operating system—that is, UNIX, Windows, and Mac OS. Each of these machines could be running on totally different hardware. For example, UNIX could be running on a Sparc workstation, Windows could be running on an Intel 80xx architecture, and Mac OS could be running on an architecture such as 68xxx or Intel 80xx. However, what is common among all three machines is the JVM. Note that the JVM, which is a software application itself, is not portable. Rather, every JVM is written for a particular target platform. The bytecode is portable across different JVMs and thus across different platforms that support the JVMs.

Robust and Secure

The introduction of the JVM in the architecture also helped developers in creating robust and secure Java applications. So what is meant by “robust and secure”? As described earlier, bytecode is interpreted by a JVM, and a JVM contains a bytecode verifier. The bytecode verifier not only verifies the validity of the bytecode, but also maintains the integrity of the memory space used by each application running on it. If the bytecode is invalid, JVM simply refuses to run the code. Similarly, if the bytecode tries to access a memory location that does not belong to the memory space of the current application, the JVM rejects the code.

Now, in the first place, how can you have invalid bytecode or an invalid memory reference in a compiled Java application? The bytecode may be modified by a malicious hacker by opening the code in a binary editor, or it may simply get modified due to noise as it is transmitted over a network. Accordingly, even the memory references may get modified in the executable before it is referenced by the JVM at runtime. Fortunately, the JVM traps such intentional and nonintentional errors before the code is executed on a real CPU, resulting in a very robust application that won’t crash your operating system.

Java code is highly secure in the sense that it cannot be used to spread a virus on a target machine. Java code that runs under the tight surveillance of the JVM does not have direct access to the operating system resources. Such access is made through the JVM, which ensures all the necessary security for the operating system.

Java has omitted one of the important features of C++, and that is pointer arithmetic. Java does not support the declaration of pointers and pointer arithmetic.

image

NOTE

Java supports object references that are essentially pointers. However, user-level pointer arithmetic is not supported.

The lack of pointers also makes Java programs more robust and secure. Pointers are notorious for allowing malicious access to locations outside the executing program’s memory space. They can also be used for spreading viruses on the system. The elimination of pointers has helped developers in creating robust and secure applications in Java.

Java is both a statically and strongly typed language. The term static refers to compile time or the source code, whereas dynamic refers to the runtime or the bytecode. A programming language is said to use static typing when type checking is performed during compile time as opposed to runtime. In static typing, all expressions have their types determined at compile time, prior to when the program is executed. The word strong in the context of typing means that rules about the typesystem are enforced prior to the code being run. Thus, Java is considered to be both statically and strongly typed.

Another important consideration in making an application robust is the proper allocation and deallocation of memory and other system resources at runtime. In C++, memory allocation and deallocation are the responsibility of the programmer. A developer may sometimes forget to deallocate a memory resource after it has been used. The worst case is when he deallocates memory that is still in use by some other part of the application. This results in chaos and hard-to-track runtime errors. Java eliminates this issue totally by providing automatic garbage collection. The Java runtime assumes the responsibility of tracking the allocations and freeing memory resources when they are no longer referenced by any part of the application. This automatic garbage collection makes Java applications very robust.

Another reason behind why Java programs are so robust is the exception-handling mechanism. Whenever an error occurs in your running program, it will be handled by an exception handler in your code, provided you have one. As a developer, you are required to provide exception handlers at all appropriate places in your program. Java has an exception mechanism with two types of exceptions—checked and unchecked. The compiler makes the developer provide code to handle the checked exceptions, but not the runtime (unchecked) ones. This mandatory requirement for processing checked exceptions results in more robust applications with fewer application crashes.

Multithreaded

The fact that Java was a multithreaded language was one of the key features hyped when the language was introduced in 1996 (…as if other languages did not support multithreading). Although most other languages do support threading, what Java provided was simpler semantics for threading. Creating threads in C++ is as easy as creating threads in Java. The difference lies in the management of shared resources. To share a resource among multiple running threads, C++ uses several constructs, including critical sections and semaphores. These are low-level constructs provided by the operating system itself. Coding for these constructs is typically very complex. Java hides the use of all these constructs underneath a newly designed keyword called synchronized. You just declare a block of code or a class as synchronized and the Java runtime takes care of the thread concurrency in accessing the shared resources. This makes thread programming in Java very simple.

image

NOTE

What was obscured from developers in early version of Java has been made available in its newer versions. The typical synchronization constructs such as semaphores, CountDownLatch, and many more are now accessible to programmers.

Dynamic

Another important feature introduced in Java is its dynamic nature. As we have seen, a Java source program compiles into bytecode. This bytecode is stored in a file with the extension .class. A running Java application can load a compile-time unknown .class file, understand the defined class, instantiate it, and use it for its own purpose. This process is called “introspection and reflection” in Java. A running Java program can introspect an unknown class, understand the attributes and operations defined in it, create an instance of the class, set the attributes of the created object, and invoke the member functions on the created object. It can also create an array of objects of this unknown type at runtime. This is the dynamic nature of Java.

image

NOTE

Smalltalk had this dynamic feature since the 1970s, Objective-C from the 1980s, and so do modern languages such as C#.

Java’s Evolution

So far, we have discussed the features of Java referring to its first version, JDK 1.0. Over time, Java has expanded a lot and has had many new features added to its repertoire. You will learn several new features in this book. In this section, we discuss the way Java has evolved over the last decade and a half.

As mentioned earlier, although Java started as a programming language for embedded devices, it has evolved into a full-fledged platform. We will look at the major milestones in Java’s evolution to its current state. Java is distributed in the form of a Java Development Kit (JDK). The several milestones in Java’s evolution are identified by the version number assigned to this JDK. The following subsections list the major releases of the JDK and the features introduced therein.

JDK 1.0 (January 23, 1996): Codename Oak

This was the first version of Java, released officially in January 1996. Prior to that Java was known as “Oak” and was mainly used internally by Sun for the development of embedded software. Embedded devices demanded portability across a wide variety of hardware and a small footprint; Java carries both these capabilities. JDK 1.0 itself was really small, with about 212 classes and eight user packages, with one additional Sun package for debugging.

image

NOTE

A Java package provides a logical grouping of classes and interfaces.

Thus, this version of Java had very limited capabilities and was no match for the libraries provided in other languages at that time. The user interface provided in the java.awt (Abstract Windowing Toolkit) package was too primitive and did not even provide a printing facility. In spite of a small feature set, Java usage picked up early in the market and within one year of its introduction Java became extremely popular.

The success behind Java at that time was due to the increasing popularity of the Internet. Web pages back then did not possess dynamic capabilities; the web pages were only static. Java applets provided dynamic content generation and interactive capabilities for web pages. Every copy of the Netscape browser provided a Java runtime. Thus, developers were able to reach a massive user base very easily by writing Java applets. This resulted in the enormous popularity and quick acceptance of Java. JDK 1.0 also provided classes for network programming, and Java was hyped at that time as a network programming language.

image

NOTE

An applet is a small Internet-based program, written in Java, that can be downloaded by any computer.

JDK 1.1 (February 19, 1997)

The next major release for Java was in February of 1997. As you can see, this major release came just one year after its original release. One can imagine the popularity that Java must have gained in this short period of time. So what major additions were made to Java in this release? The number of classes in JDK 1.1 was 504 and the number of packages was 23. These figures speak to the number of additions made to the Java APIs. Thus, although the change in release number was minor, this was in fact a major change.

The major change in the Java language at this time was the new event-processing model. JDK 1.0 used the hierarchical event model used by Windows operating systems. JDK 1.1 and above use the delegation event model, which is more efficient compared to the older model. This helped improve Java’s performance, which was highly desired because Java in those days lacked in performance due to its compiled and interpreted nature, as explained earlier. Programming for the delegation event model may employ the newly added anonymous and inner classes for improved efficiency.

JDK 1.1 had many minor releases over next two years, until its last release, which was JDK 1.1.8 in April 1999. Each release added new classes and interfaces to the library, and thus Java was growing every day. Some of the major milestones in these minor releases are detailed next.

Java Beans

The JavaBeans API was introduced during this period for component development in Java. Java Beans are reusable software components, written in Java, that can be manipulated visually in a builder tool. Thus, you could build sophisticated GUIs (graphical user interfaces) visually by using third-party components based on the JavaBeans API.

Remote Method Invocation

JDK 1.1 also introduced Remote Method Invocation (RMI), which allows a client to invoke a method on an application running on a remote server. RMI used a proprietary binary protocol called the Java Remote Method Protocol (JRMP). Later on, a newer protocol, called the Internet InterORB Protocol (IIOP), was widely accepted by the industry and became preferred over JRMP. IIOP was designed as part of the Common Object Request Broker Architecture (CORBA). To bridge the gap between the two protocols, Java also introduced RMI over IIOP.

The JAR File Format

A Java applet may consist of many source files. When such applet code is compiled, it generates a separate object code (.class) file for each public class or interface. When the applet code is downloaded to the client machine, all such .class files must be downloaded before the applet can begin its execution. The HTTP 1.0 protocol required the creation of a separate socket connection for each file download. Typically, each .class file is a few hundred bytes in size. The time required to make a connection and disconnection was much longer than the time required for each file download. To resolve this problem, JDK 1.1 introduced the JAR concept, whereby all applet .class files were archived in one single file using the PKZIP algorithm. The resultant JAR file was referenced in the APPLET tag of the HTML code. The client would now download one single JAR file using a single socket connection. This resulted in faster download and a much better application startup time on the client’s end.

Digital Signatures

Another major change provided in JDK 1.1 was the introduction of digital signing. In JDK 1.0, a Java applet would run in a sandbox with several security restrictions and limited access to system resources; conversely, a stand-alone Java application runs outside the sandbox with full access to all the system resources. With digital signing, applets that were generally deployed on remote servers could now be trusted after their signatures were verified. The client would grant full privileges of a stand-alone application to such verified signed applets.

AWT Enhancements

The AWT, which contains the interfaces and classes for building the GUI, provided several enhancements in JDK 1.1. The most noticeable change was the new event model mentioned earlier. Besides this, several other additions were made to the AWT package. The GUI now supported data transfer using the clipboard so that you could cut/copy/paste the contents of your documents from even a native application to a Java application, and vice versa. You could set and use desktop colors in your Java applications. You could also define shortcut keys for menu items. It also became possible to create pop-up menus like the ones in applications running on Microsoft Windows.

Finally, AWT classes added printing support. Printing was not at all possible in JDK 1.0. AWT also added a ScrollPane container for displaying large documents in windows with scrollbars. Note that even such basic facilities were not available in JDK 1.0, and it received wide acceptance in the very short period of one year. Thus, Java had a promising future, as was proved by now.

Other Changes

Some of the other noticeable changes in JDK 1.1 included the introduction of object serialization classes, the Introspection and Reflection API, and the facility to define Inner classes. In addition, general performance improvements were made in several places.

J2SE 1.2 (December 8, 1998): Codename Playground

The next milestone for Java came in December 1998. This version had 1,520 classes and 59 packages. You can clearly see how fast Java grew in just three years. During this time, Sun also introduced a new terminology to describe Java technology—Java SE (Standard Edition). The name JDK is still used to describe an implementation of this technology.

The Introduction of Swing

The major feature introduced in Java 2 was Swing—the new Java-based GUI classes. This made the earlier AWT classes somewhat obsolete, except that Swing extended those classes. AWT components are considered heavyweight because they use many native operating system calls. The new Swing-based GUI classes are totally Java based and therefore are lightweight. These Java-based classes provided the advantage of on-demand installation in browsers that refused to add support to the new JDK versions; this was the case with Microsoft’s Internet Explorer (readers may be aware of the famous legal suit between Microsoft and Sun Microsystems during this period). Swing classes also permitted the “pluggable look and feel” (PLAF) that allowed developers to change the look and feel of their applications to whatever they would like. Swing supported Windows, Motif, and Java native platforms.

image

NOTE

The Java platform at that time was commonly known as Java 2, even though the official name was J2SE 1.2.

The 2D API

The JDK now included classes for the 2D API to allow the user to create two-dimensional charts and graphs easily with the help of several predefined classes and interfaces. The 2D API is the basis for all the drawing in the Java SE platform, not just for charts and graphs.

Drag-and-Drop

J2SE 1.2 introduced the drag-and-drop facility for selecting contents in a Java application and then dragging and dropping them into a native application, and vice versa. Thus, you could now drag and drop the contents of a Microsoft Word document into a Java application, as well as the other way around. This is done without copying and pasting the contents to a clipboard.

Audio Enhancements

The JDK now provided classes for playing back MIDI files and a full range of .wav, .aiff, and .au files. It also provided much higher sound quality.

Java IDL

Java IDL is CORBA’S ORB (Object Request Broker) implemented on the Java platform. This facilitated integration of Java applications with existing CORBA clients and servers. Java provided both CORBA IDL (Interface Definition Language) to Java Interfaces mapping and Java to CORBA IDL reverse mapping. This made it possible to protect the investments in both existing Java Client and RMI-based Java applications.

Security Enhancements

Java security is now policy based. Digital signing was introduced in JDK 1.1. This allowed the identification of the applet source; however, it was not possible to assign different privileges, depending on the source of the applet. In other words, there was no differentiation between two different trusted applets or between a trusted applet and a stand-alone application. All would acquire the same privileges. J2SE 1.2 resolved this issue by creating policy-based security. One can now define a security policy based on the source of the applet. In this way, different applets would be subject to different policies defined by their user and thus acquire different sets of privileges. This also applies to stand-alone Java applications that were also subject to user-defined policies. The policy files are text based and easily configurable. Java also provided a policy tool to create and maintain policies. The policies enabled the fine-grain access control to system resources.

Other Enhancements

In addition to the aforementioned major changes, several enhancements were made to improve performance in general. The loaded classes now had better memory compression. The memory allocation and garbage collection had improved algorithms for faster allocations and deallocations. The Just-in-Time (JIT) compiler mentioned earlier was introduced in this version of Java. New classes such as ArrayList and BufferedImage and APIs such as Collections were added. DSA code signing was also added.

image

NOTE

At the time the Java 2 platform was introduced, Java ventured into another arena, known as server-side Java. A separate bundle of Java classes was introduced for this purpose and was called J2EE (Java 2 Enterprise Edition). This included classes for server-side component developments such as Servlets. J2EE has also gone through several major revisions and now includes classes for creating server-side components such as Enterprise Java Beans (EJBs), Java Server Pages (JSPs), Java Database Connectivity (JDBC), J2EE connectors, and more. By this time, Java was clearly split into two areas: the server-side Java (J2EE, now called Java EE) and the standard edition of Java (J2SE). Because this book focuses only on the standard edition of Java, we will not discuss J2EE further.

J2SE 1.3 (May 8, 2000): Codename Kestrel

The next major release of Java, known by this time as J2SE (Java 2 Standard Edition), came in May of 2000. It was codenamed Kestrel and was also called Java 2, Release 1.3. This version did not make lots of additions to its predecessor. The number of classes increased from 1,520 to 1,840, and the number of packages increased from 59 to 76. The notable changes included the bundling of the HotSpot JVM (first released in April 1999 for J2SE 1.2 JVM), JavaSound, Java Naming and Directory Interface (JNDI), and Java Platform Debugger Architecture (JPDA). JNDI provides Java-platform-based applications with a unified interface to multiple naming and directory services in the enterprise, including Lightweight Directory Access Protocol (LDAP), Domain Name System (DNS), Network Information Service (NIS), Common Object Request Broker Architecture (CORBA), and file systems. Like all Java APIs, JNDI is independent of the underlying platform. The service provider interface (SPI) allows directory service implementations to be plugged into the framework, which may make use of a server, a flat file, or a database.

The RMI API had several enhancements—strings longer than 64K could now be serialized, and rmid now required a security policy file, to name a couple. Two new methods were added in the DataFlavor class of the drag-and-drop API. Several additions were made to the Java 2D API, including support for Portable Network Graphics (PNG) format. Besides these, many changes were made to Swing, AWT, Security, and Object Serialization APIs. The java.math package was enhanced, and some classes were added, including the Timer class, the StrictMath class, the print class, and the java.media.sound class. This API introduced Hotspot and RMI over IIOP (discussed earlier). The RSA code signing was also added.

The next minor release was J2SE 1.3.1, codenamed Ladybird, which was released on May 17, 2001.

J2SE 1.4 (Feb 6, 2002): Codename Merlin

This was the first release of the Java platform developed under the Java Community Process (JCP) as Java Specification Request (JSR) 59. It consisted of 2,991 classes in 135 packages. Major changes included regular expressions modeled after Perl, exception chaining, an integrated XML parser, an XSLT processor (JAXP), and Java Web Start. To support regular expressions, a new package called java.util.regex was added that contained classes for matching character sequences against patterns specified by regular expressions. You will learn about exception chaining in Chapter 8. The JAXP (Java API for XML processing) provides basic support for processing XML documents though a standardized set of Java Platform APIs. Java Web Start software provides a flexible and robust deployment solution for Java-technology-based applications.

image

NOTE

The JCP is the mechanism for developing standard technical specifications for Java technology. The JSR is the actual description of proposed and final specifications for the Java platform.

Besides these, several changes came in the AWT package to improve the robustness, behavior, and performance of GUI-based programs. Likewise, many new features were added to Swing, including a new spinner and formatted text field components as well as support for drag-and-drop. The Popup and PopupFactory classes were exposed to programmers, thus allowing them to create their own pop-ups. JDBC, which provides universal data access from the Java programming language, was enhanced to JDBC 3.0 API. The new features included the ability to set savepoints in a transaction, to keep result sets open after a transaction is committed, to reuse prepared statements, to get metadata about the parameters to a prepared statement, to retrieve keys that are automatically generated, and to have multiple result sets open at one time. It also included two new JDBC data types: BOOLEAN and DATALINK. The DATALINK data type makes it possible to manage data outside of a data source. The new I/O (NIO) APIs provided new features and improved performance. Besides these changes, additions were made to RMI, Math, Collections Framework, Accessibility, and the Java Native Interface (JNI).

The other minor releases that followed were J2SE 1.4.1 (September 16, 2002), codenamed Hopper, and J2SE 1.4.2 (June 26, 2003), codenamed Mantis.

J2SE 5.0 (Sept 30, 2004): Codename Tiger

Developed under JSR 176, Tiger added a number of significant language features, including the for-each loop, generics, autoboxing, and var-args. Because this book focuses on J2SE, we cover most of the additions made in this release. This release had 3,562 classes in 166 packages.

Generics allow a type or method to operate on objects of various types while providing compile-time type safety. This was added to all the classes in the Collections Framework. You learn about generics in Chapter 12. The enhanced for loop eliminates the drudgery and error-proneness of iterators and index variables when iterating over collections and arrays. (You can learn about this enhanced for loop in Syntax Reference 3, one of the three web chapters.) The autoboxing/unboxing feature eliminates the drudgery of manual conversion between primitive types and wrapper types. Chapter 11 fully covers this feature. The var-args allow you to specify a variable number of arguments on program invocation. This is covered in Chapter 9. Besides these, typesafe enums were introduced in this version, which are covered in Chapter 11. The newly added static import facility lets you avoid qualifying static members with class names without the shortcomings of the “Constant Interface anti-pattern.” Additionally, changes and enhancements were made to Internationalization APIs. Internationalization is the process of designing an application so that it can be adapted to various languages and regions without engineering changes. Sometimes the term internationalization is abbreviated “i18n,” because there are 18 letters between the first letter (i) and the last (n). Besides these, the following APIs were enhanced: JavaSound and Java 2D technologies, Image I/O, AWT, and Swing. The java.lang and java.util packages had several enhancements, including the new Formatter and Scanner classes, which you will be using in several programming examples in this book. There were lots of enhancements to Concurrency Utilities and the Collections Framework. We cover all major enhancements to Concurrency Utilities in Chapter 19 and those in the Collections Framework in Chapter 16. On the hardware front, AMD Opteron processors are now supported by the server VM on SUSE Linux and on Windows 2003.

Java SE 6 (Dec 11, 2006): Codename Mustang

This release facilitated the use of scripting languages (JavaScript using Mozilla’s Rhino engine) with the JVM and provided Visual Basic language support. As of this version, Sun replaced the name “J2SE” with Java SE and dropped the “.0” from the version number. This release introduced several changes and additions to the Collections Framework. New interfaces, named Deque, BlockingDeque, NavigableSet, NavigableMap, and ConcurrentNavigableMap, were added. A few concrete implementation classes were added, and the existing classes were retrofitted to implement new interfaces. We discuss the Collections Framework in Chapter 16. Several enhancements were made in the java.lang.instrument package. The Instrumentation API provides services that allow Java programming language agents to instrument programs running on the JVM. We do not cover instrumentation in this book. The java.io package introduced a new class called Console, which will be covered in Chapter 9. This class contains methods to access a character-based console device; its readPassword method allows input of sensitive data such as passwords by disabling echoing of characters on the console. The File class now has several methods to retrieve disk usage information as well as setting and querying file permissions. We discuss this class in Chapter 9. The JAR and ZIP API was also enhanced. In addition, enhancements were made in Java Web Start and the Java Network Launching Protocol (JNLP), which provides a browser-independent architecture for deploying Java 2 technology-based applications to the client desktop.

Other major changes included support for pluggable annotations (JSR 269), lots of GUI improvements, including native UI enhancements to support the look and feel of Windows Vista, and improvements to the JPDA and JVM Tool Interface for better monitoring and troubleshooting.

Java SE 7 (July 7, 2011): Codename Dolphin

Java SE 7 is the major release to the Java SE platform, which came a long time after its previous release. It introduced many enhancements to the Java language. Integral types can now be expressed using the binary number system. Numerical literals can contain underscore characters for better readability. You can use strings in switch statements. A diamond operator is introduced in generics instance creation syntax. A new try-with-resources statement has been added. Multiple exception types may now be included in a single catch block. A new compiler option and two annotations are added to give you improved compiler warnings and errors when using nonreifiable formal parameters with var-args methods. Many of these features are covered in the relevant chapters in this book.

Java SE 7 introduced the NIO.2 API, which offers the ability to develop a custom file system provider for managing file system objects. The new additions to this API provide comprehensive support for file I/O and for accessing the file system. We cover this in Chapter 9. The JDBC 4.1 API enables you to use try-with-resources syntax to automatically close resources of type Connection, Resultset, and Statement. Additions have been made to RowSet that enable you to create all types of row sets supported by your JDBC driver. Java SE 7 adds support for Stream Control Transmission Protocol (SCTP) on Solaris and Sockets Direct Protocol (SDP), which is a wire protocol to support stream connections over InfiniBand fabric. This, at the time of this writing, was available for the Solaris and Linux platforms. You can now develop and deploy Rich Internet Applications as applets or Java Web Start applications. Because this is an altogether different domain of applications that would require another book to describe, we do not cover these APIs in this book. The Java SE platform now supports the implementation of dynamically typed programming languages on the JVM; for this, a new instruction called invokedynamic was added to the JVM. Although the Introspection and Reflection API is covered thoroughly in Chapter 21, we do not cover the use of this instruction because it is not at all relevant to the context of this book. A lightweight fork/join framework is now added to the Concurrency API. This is covered fully in Chapter 19. On the client side, Java SE 7 adds a next-generation cross-platform look and feel for Swing—called Nimbus look-and-feel. This is used in several applications in this book. Besides these, there are several other enhancements that are not relevant to the context of this book. For example, the XML stack has been updated to support the most recent versions of XML processing, binding, and Web Services APIs. The MBeans API is enhanced to add more management functionality. In the Security and Cryptography API, a portable implementation of the standard Elliptic Curve Cryptographic (ECC) algorithms has been added. The Internationalization API is enhanced to support the 6.0 version of Unicode. The Locale class has been upgraded, and the handling of locales has been upgraded to separate formatting locales from user interface language locales. The reader is encouraged to visit the openjdk site (http://openjdk.java.net/projects/jdk7/features/) to look at the rest of the changes that came in the Java SE 7 platform.

Summary

Java, since its public introduction in 1996, has become extremely popular among developers worldwide—mostly because of its cross-platform nature. Today it has evolved into a full-fledged platform for creating, deploying, and running a wide variety of applications. To achieve portability, Java uses the concept of a virtual machine (VM). A Java source file compiles into bytecode consisting of an instruction set of a pseudo CPU. This CPU is emulated in memory by a running process, and the compiled bytecode runs on the emulator. This allows Java executables to run on any platform that has a JVM (Java Virtual Machine). Java’s major features of note are that it is small, simple, object oriented, compiled and interpreted, platform independent, robust and secure, multithreaded, and dynamic. We discussed each of these features in depth in this chapter.

Java has undergone several revisions over the last 15 years. These revisions are marked by the versioning of the Java Development Kit. JDK 1.0 was introduced in 1996, and the next major release, JDK 1.1, came about just one year later. Over next several years, Java evolved into several distinct platforms: Java SE (Java Platform, Standard Edition), Java EE (Java Platform, Enterprise Edition), Java ME (Java Platform, Micro Edition), and Java Card technology. We discussed the important features and additions in all the major releases of the Java SE platform in this chapter.

With this brief introduction to the exciting Java platform, let’s start learning it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.8.110