21. Java
21.3 The Java Language
The Java programming language and environment is designed to solve a number of problems in modern programming practice. It has many interesting features that make it an ideal language for software development. In this section we describes the features of Java as compared to C and C++, introduces the Java predefined classes, and talks about some limitations of Java language and how these limitations are addressed.
Readers who are interested in Java security or would like to see Java in the context of distributed computing, can go to Chapter 14 or Chapter 19.
In its white paper (1995), Sun describes Java as simple, object-oriented, distributed, robust, secure, architecture neutral, portable, interpreted, high performance, multithreaded and dynamic.
The most important simplification is that Java does not use pointers (one of the most bug-prone aspects of C and C++ programming language) and implements automatic garbage collection so that we don't need to worry about dangling pointers, invalid pointer references, and memory leaks and memory management.
In order to keep the language small, One design goal has been to enable the construction of software that can run stand-alone in small machines. The size of the basic interpreter and class support is about 40k bytes; the basic standard libraries and thread support require an additional 175K.
By now we should have a good idea of what Java language is all about. These interesting features of Java language are where Java is different from other languages and where Java gets started; they are embodied in Java's predefined classes (Java Base API). We describes these classes in the next subsection.
The default Java environment currently consists of several different Java packages implementing a diverse set of fundamental classes. They include the following:
The java.lang package contains the basic java classes and native types: Class, Object, Boolean, Float, Double, Integer, String, and so on plus those dealing with the extended capabilities of the language (e.g. SecurityManager, Thread, and Throwable -- the root class of the Java exception and error hierarchy) and connection with the rest of the system environment.
The java.awt package is the Abstract Windowing Toolkit which allows you to deal with GUI objects in a generic manner without regard to the system on which your program in running. The big advantage is that your program will automatically run on all supported Java platforms. The current java.awt is a least-common-denominator GUI toolkit; it dispenses with the totally inessential cosmeticisms. The classes of this package may be roughly divided into three categories:
The java.awt.peer package consists entirely of interface definitions. Each java.awt.peer interface corresponds to one of the java.awt Component or MenuComponent classes. The interfaces in this package define the methods that must be supported by the GUI components on a specific platform. The Abstract Windowing Tookit contains methods that create instances of each of the interfaces in this package. Normal applications never need to instantiate these peers directly; instead they use the java.awt Component classes, which create peers as needed.
The java.applet package contains the Applet class, which is the superclass of all applets. An applet is a graphic piece of larger program, focused primarily on providing some form of browser-related contents. This class implements an applet. To create your own applet, you should create a subclass of this class and override some or all of its methods. Your will never need to call the methods defined in the Applet class -- they are called when appropriate by a Web browser or an applet viewer.
The java.io package contains classes to support reading and writing streams, files, and pipes. These classes form a fairly structured hierarchy -- most of them are subclasses of InputStream or OutputStream.
The java.net package contains classes to support network programming. These include dealing with sockets, Internet addresses, network datagrams, uniform resource locators (URLs), and content handlers for data from a URL. To name a few, the URL class provides a very simple interface to networking -- the object referred to by the URL can be downloaded with a single call, and the Socket class allows you to connect to a specified port on a specified Internet host and read and write data using the InputStream and OutputStream classes of the java.io package.
The java.util contains general-purpose utility classes for data structures, such as dictionaries, hashtables, dates, stacks, bits, and strings. Since Java depends directly on several of the classes in this package, we should not consider it to be a ``utility'' package separate from the rest of the language.
Java has many language features that lead to more robust programs with less coding. These include OOP classes, garbage collection, C syntax, uniform data sizes, boolean and string types, exception handling, final clause, labeled break and continue, strong typing, array boundary checking. The philosophy of using computing power to achieve better program reliability is well-established in Java. The principle of using computing power to save programming effort is less pronounced, but still an important part of Java's eventual acceptance. This is one area in which Java made the right trade-off.
With all the hype around Java, we also hear some discrepancies on what Java has achieved (Nombas, Shiffman) . Here are some issues we would like to discuss.
Much of the popular press is claiming that Java is much easier to learn than C++, heralding it as a breakthrough in that regard. Certain aspects of Java are easier to learn than C++, but the difficulties most people have in learning to program in both C++ and Java have little to do with the language itself. Instead, that have to do with fundamental object-oriented concepts. Java is somewhat easier than C or C++ not because its syntax is any simpler, but more because there are fewer surprises.
Java source code is more portable than C-based languages. In C and C++, each implementation decides the precision and storage requirements for basic data types. Java avoids this major source of porting problems by defining the size of basic types for all implementations.
Some people (see Shiffman) points out that while storage requirements for float and double are defined by Java, precision during calculation is not. This means that that a program that uses floating point arithmetic can produce different answers on different systems, with the degree of difference increasing with the number of calculations a particular value goes through.
Java is more portable than other languages in its object code. Most language compilers generate the native code for the target computer, which then runs at the best speed of which the system is capable. Java compiles to an object code for a theoretical machine; the Java interpreter emulates the machine. The trade off is in performance.
Due to its portable byte code, the same Java applet will run anywhere the Java Virtual Machine runs. But Java doesn't solve all the problems of cross-platform development. There are a few major limitations to Java's ability to do clean cross-platform execution.
Theoretically Java may be perfectly suitable for a big project. But we should also consider the following factors:
The larger is the size of an application, the more severely these factors will affect the performance.
For a lot of reasons, Java is likely to always be slower than C++ and Fortran for typical application. Some of these reasons are:
With the growing popularity, the issue of performance is becoming more and more important. In the beginning, many people believe that Java is likely to be always slower than C++ for typical application. (A range of 50% to 300% slower than C++ has been suggested as the practical limit of Java performance improvements.) But, with the coming of JavaOS and the JavaChip Family, or using the Just-In-Time compilation, we can expect a huge improvement in performance for Java applications.
At the early stage of the development of Java language, the goal of the Java's creators was to build a system that has the capability of doing a large, distributed, heterogeneous network of consumer electronics devices all talking to each other. Even till June 1994 when they retargeted Oak at the Internet, the priority on the creators' agenda was to achieve the architecture neutrality. However, after Java took the World Wide Web by storm, the issue changed. Java's success has been gaining tremendous popularity; people are itching to play around with Java and developers are planning to develop their applications using Java. Java is expected to be able to do more. The issue of performance should now be on the top of the priority list of the Java creators.
To greatly improve the performance and portability of the Java Platform, JavaSoft has implemented a optional Just-In-Time compilation in the Java Virtual Machine, and made available the JavaOS and picoJava (a specification for a microprocessor for running Java bytecode.).
Both the JavaOS and the JavaChip Family eliminate the overhead of host operating system and therefore improve the application performance. The performance improvement achieved by JavaOS will be discussed in the JavaOS section. The performance improvement gained by picoJava is not yet available, but we can reasonably expect a great performance improvement since the Java Platform is build directly on hardware in this case. Also, because the JavaOS and JavaChip Family can be adapted to embedded devices where hardware resources are much more restricted, the Java Platform can penetrate into places where other platforms can not. This certainly improves the portability of the Java Platform and makes it available in a wider range of OS and hardware.
The JIT (Just-In-Time) compiler greatly improves the performance by directly turning the bytecodes into machine code, reports of comparisons between platform with JIT and platform without JIT are available. For example, a CaffeineMark test with the Symantec JIT (Win NT) compiler gave Loop test scores that were 19 times faster than with the Sun JDK (WIN 95 ) that does not have a JIT. The following comparison chart is prepared by Brinan W. Case. More details are available in JIT Compiler Results.
166-MHz Pentium, 512K PB cache, 32M memory, Win95, WinNT, Linux 1.3.83 kernel.
Platform | Sieve | Loop | Graphics | Image | CaffeineMark |
---|---|---|---|---|---|
Borland JIT (Win NT) | 809 |
2130 | 298 |
147 | 848 |
Symantec JIT (Win NT) | 1116 |
1240 | 331 |
158 | 713 |
Borland JIT | 345 | 1315(?) |
96 | 92 | 461 |
Symantec JIT | 386 | 929 |
102 | 99 | 379 |
Sun JDK (Linux) | 64 | 58 |
200 | 162 | 121 |
Netscape (Linux) | 44 | 38 |
183 | 123 | 97 |
Symantec without JIT | 75 | 79 |
94 | 85 | 83 |
Sun JDK (Win95) | 58 | 50 |
91 | 81 | 69 |
Netscape (Win95) | 34 | 32 |
77 |
51 | 48 |
Brian's Notes: I included only the set of numbers that led to the best overall CaffeineMark. There was considerable variability in some numbers on some platforms (e.g., Sun JDK, Linux, Graphics from 175 to 200). Thus, these might be "guaranteed not to exceed" numbers. The Borland JIT Loop number has a question mark because [the last] digit was painted outside the applet;
Java's creators have been working the hardest on the Java Platform. They well address some of issues we mentioned in Java Limitations, such as performance and portability. It is likely that the Java Platform will become a ideal platform for the end users, software development and software maintenance.
Copyright 1996 Guowei Huang, All Rights Reserved
Guowei Huang
<ghuang@csgrad.cs.vt.edu>
Last modified: Sun Nov 24 11:50:05 1996