|
Java is an object-oriented programming language developed primarily by James Gosling and colleagues at Sun Microsystems. The language, initially called Oak (named after the oak trees outside Gosling's office), was intended to replace C++, although the feature set better resembles that of Objective C.
Specifications of the Java language, the JVM and the Java API are community-maintained through the Sun-managed Java Community Process.
History
Main article: History of Java
Java was developed in 1991 by James Gosling and other Sun engineers, as part of the Green Project. After first being made public in 1994, it achieved prominence following the announcement at 1995's SunWorld that Netscape would be including support for it in their Navigator browser.
Overview
There were four primary goals in the creation of the Java language:
- It is object-oriented.
- It is independent of the host platform (more or less).
- It contains language facilities and libraries for networking.
- It is designed to execute code from remote sources securely.
Language characteristics
Object orientation
The first characteristic, object orientation ("OO"), refers to a method of programming and language design.
Although there are many interpretations of OO, one primary distinguishing idea is to design software so that the various types of data it manipulates are combined together with their relevant operations. Thus, data and code are combined into entities called objects. An object can be thought of as a self-contained bundle of behavior (code) and state (data). The principle is to separate the things that change from the things that stay the same; often, a change to some data structure requires a corresponding change to the code that operates on that data, or vice versa. This separation into coherent objects provides a more stable foundation for a software system's design. The intent is to make large software projects easier to manage, thus improving quality and reducing the number of failed projects.
Platform independence
The second characteristic, platform independence, means that programs written in the Java language must run similarly on diverse hardware. One should be able to write a program once and run it anywhere.
This is achieved by most compilers by compiling the Java language code "halfway" to bytecode—simplified machine instructions specific to the Java platform. The code is then run on a virtual machine (VM), a program written in native code on the host hardware that translates generic Java bytecode into usable code on the hardware. Further, standardized libraries are provided to allow access to features of the host machines (such as graphics, threading and networking) in unified ways.
There are also implementations of Java compilers that compile to native object code, such as GCJ, removing the intermediate bytecode stage, but the output of these compilers can only be run on a single architecture.
Sun's license for Java insists that all implementations be "compatible". Some vendors, notably Microsoft, have insisted on adding platform-specific features (for example, in Microsoft's case, for Windows) and Sun has reacted strongly. Many industry observers saw Microsoft's extensions to Java as part of an embrace and extend strategy to take over or extinguish Java as a competitor platform to the Windows API. After Microsoft insisted on retaining its incompatible variations, Sun sued and won both damages (some $20 million dollars) and a court order enforcing the terms of the license from Sun.
Microsoft has taken the position that a compliant Java, meeting the terms of the license as ordered by the court, is inadequate and has decided to leave out any Java system at all in future versions of Microsoft Windows. This means that stock versions of Internet Explorer in such versions of Windows will break for Web sites using Java applets. Sun and others have made available Java run-time systems at no cost for those versions of Windows without Java. The necessity to download them is a consequence of the litigation and Microsoft's decision to comply with the court's order by leaving out Java support.
The first implementations of the language used an interpreted virtual machine to achieve portability, and many implementations still do. These implementations produce programs that run more slowly than the fully-compiled programs created by the typical C++ compiler and some later Java-language compilers, so the language suffered a reputation for producing slow programs. More recent implementations of the Java VM produce programs that run much faster, using multiple techniques. There is still a speed difference, but it is much smaller.
The first technique is to simply compile directly into native code like a more traditional compiler, skipping bytecodes entirely. This achieves great performance, but at the expense of portability. Another technique, known as just-in-time compilation (JIT), compiles the Java bytecodes into native code at the time that the program is run.
More sophisticated VMs even use dynamic recompilation, in which the VM can analyze the behavior of the running program and selectively recompile and optimize critical parts of the program. Both of these techniques allow the program to take advantage of the speed of native code without losing portability.
Portability is a technically difficult goal to achieve, and Java's success at that goal is a matter of some controversy. Although it is indeed possible to write programs for the Java platform that behave consistently across many host platforms, the large number of available platforms with small errors or inconsistencies led some to parody Sun's "Write once, run anywhere" slogan as "Write once, debug everywhere".
Platform-independent Java is, however, very successful with server-side applications, such as web services, servlets, or Enterprise Java Beans.
Automatic garbage collection
One major problem with languages such as C++ is the need for manual memory management. In C++, memory must be allocated by the programmer to create an object, then deallocated to delete the object. Often a programmer forgets or is unsure when to deallocate, leading to a memory leak, where a program consumes more and more memory without cleaning up after itself. Even worse, if a region of memory is deallocated twice, the program can become unstable and crash.
In Java, this problem is solved by automatic garbage collection. Objects are created and placed at an address on the heap. The program or other objects can reference an object by holding a reference to its address on the heap. When no references to an object remain, the Java garbage collector automatically deletes the object, freeing memory and preventing a memory leak. Memory leaks, however, can still occur if a programmer's code holds a reference to an object that is no longer needed—in other words, they still occur but at higher conceptual levels. But on the whole, Java's automatic garbage collection makes creation and deletion of objects in Java much easier and safer than in C++.
Interfaces and classes
One thing that Java accomodates is creating an interface which classes can then implement. For example, you can create an interface like this:
public interface Deleteable {
void delete();
}
This code says that any class that implements the interface Deleteable will have a method named delete(). The exact implementation and function of the method are determined by each class. There are many uses for this concept; for example, the following could be a class:
public class Fred implements Deleteable {
//Must include the delete () method to satisfy the Deleteable interface
public void delete() {
}
//Can also include other methods
public void doOtherStuff() {
}
}
Then, in another class, the following is legal code:
public void deleteAll (Deleteable[] list) {
for (int i = 0; i < list.length; i++)
list[i].delete();
}
because any objects in the array are guaranteed to have the delete() method.
The purpose is to separate the details of the implementation of the interface from the code that uses the interface. For example, the Collection interface lists a bunch of methods that any collection of data might want to implement, like getting data or adding data, but a specific collection could be an array, or a linked list.
The feature is a result of compromise. The designers of Java decided not to support multi-inheritance but interfaces can be used to simulate multi-inheritance in some occasions.
Interfaces in Java work differently than in other object-oriented programming languages — Java interfaces behave much more like the concept of the Objective-C protocol.
Encoding independence
The language distinguishes between bytes and characters. Characters are stored internally using UTF-16, and Java program source may contain any Unicode character.
Miscellaneous
Although the language has special syntax for them, arrays and strings are not primitive types: they are objects.
Evaluation
Most consider Java technology to deliver reasonably well on all
these promises. The language is not, however, without drawbacks.
Java tends to be more high-level than similar languages (such as C++), which means that the Java language lacks features such as hardware-specific data types and low-level pointers to arbitrary memory.
Although these features are frequently abused or misused by programmers, and make it harder (though far from impossible) to write a reliable, secure program, they are also powerful tools. However, the Java Native Interface (JNI) does provide a way for a Java program to call non-Java code in order to use the capabilities of other languages when necessary.
Some also see a shortcoming in its lack of multiple inheritance, a powerful feature of several object-oriented languages such as C++, Eiffel, and CLOS. Java subclasses have only one chance to inherit implementation by choosing one superclass, which can lead to false dilemmas (should HouseBoat inherit House or Boat?) and rules out certain implementation techniques such as mixins. However, proponents believe Java's ability for classes to implement multiple interfaces is a good trade-off, providing most of the benefits of full multiple inheritance while sidestepping thorny situations in which a class inherits multiple conflicting implementations.
Java's paradigm of bytecode interpretation is widely seen to provide portability only at the expense of performance degradation relative to native code. Dynamic compilation helps tremendously, but still typically cannot beat statically-compiled code. This is because when compilation occurs at run-time and thus counts against the performance of the program, the compiler must use its powerful, expensive optimizations very sparingly. However, precisely because dynamic compilers are present at run-time, they can take advantage of dynamic program behaviour, and can even recompile portions of the program as conditions change. Therefore, dynamic compilers can perform optimizations that static compilers cannot; and there are some programs for which dynamically compiled code is faster than statically compiled. (For instance, long-running programs whose behaviour depends on input data may fall into this category.)
It is not unreasonable to suppose that this set of programs will grow as dynamic-compilation technology improves.
Java's heavy use of heap-allocated objects causes programs to consume more memory than similar programs written in lower-level languages, where data storage can be optimized at a fine granularity. Because it treats almost everything as an object, Java encourages a style in which objects contain many references to other objects rather than raw data, making the objects larger and the data less localized. Both of these effects tend to work against modern memory hierarchies, whose caching schemes thrive on small working sets and good locality.
There are some who believe that, for certain projects, object orientation makes work harder instead of easier. This particular complaint is not unique to the Java language but applies to other object-oriented languages as well.
Responses to the language
Java has been lauded for what some see as being simpler than other popular object-oriented languages such as C++, its garbage collection mechanisms as simplifying memory management, and having a consistent set of classes available across supported platforms. However, natural objections arise to some of these positive points of Java, such as garbage collection encouraging lazy programming and its efficiency concerns.
Yet, underlying Java, there tends to be more subtle concerns with the implementation of the language in particular. Java is closely modeled on Objective-C, a dynamically typed hybrid object-oriented programming language. Java implements an Objective-C like generic class, Object, which can be used in container classes. However Java is not truly dynamically typed, which can result in forced clumsy use of the class. For example, if we have a container class with class methods Object pop() and void push(Object o), and instance called stack, when we add say an Integer with the push method, we must always invoke it as
stack.push(new Integer(number))
and we must always retrieve the element as
Integer x = ((Integer) stack.pop());
This may not seem such a bad thing, but the chaining of method calls can become cumbersome, for example, one could well write
int x = ((Integer) ((Node) linkedlist.node()).data()).intValue();
Some argue that having this style of type restrictions enforces type safety, but that casting breaks the discipline of strong typing. However, Java objects know their own class, and cannot be cast into incorrect classes or interfaces; any attempt to do so generates a ClassCastException, so in fact strong typing is always preserved. Storing an incorrect type in a container may only be discovered at runtime, but it will never corrupt the data by treating it as a different type, as happens all too often in C/C++.
In response to such criticisms, Java 2 Version 5 (the renamed version 1.5; see below) has support for generic programming, eliminating the need for such casts.
In addition to generics another language feature, known as Autoboxing eliminates the need for an explicit promotion between primitive and Object types. The J2SE 5.0 example can then be re-written as
stack.push(number)
and retrieved without the cast
Integer x = stack.pop();
and without the explicit conversion
int x = (linkedlist.node()).data();
In Objective-C, by comparison, the above method calls are written:
[stack push:number]
Integer *x = [stack pop]
int x = [[[linkedlist node] data] intValue]
Since Objective-C uses dynamic typing, the casts need not be explicitly specified by the programmer.
Input/Output
Versions of Java prior to 1.4 only supported stream-based blocking I/O. This required a thread per stream being handled, as no other processing could take place while the active thread blocked waiting for input or output. This was a major scalability and performance issue for anyone needing to implement any Java network service. Since the introduction of NIO (New IO) in Java 1.4, this scalability problem has been rectified by the introduction of a non-blocking I/O framework (though there are a number of open issues in the NIO API as implemented by Sun).
The non-blocking IO framework, though considerably more complex than the original blocking IO framework, allows any number of "channels" to be handled by a single thread. The framework is based on the Reactor Pattern.
The following code snippet shows how user input is accepted from a keyboard and displayed back using stream-based blocking IO. Note that the main thread will block while waiting for input from standard input. If one wanted, for instance, to display a blinking cursor, another thread would have to be created to create the blinking effect.
public static void main(String[] args) throws java.io.IOException {
char a;
System.out.println("Welcome user, please enter a letter");
a = (char) System.in.read();
System.out.println("Your letter was " + a);
}
APIs
Sun has defined 3 platforms targeting different application environments and segmented many of its APIs so that they belong to one of the platforms. The platforms are:
The classes in the Java APIs are organized into separate groups called packages. Each package contains a set of related interfaces, classes and exceptions. Refer to the separate platforms for a description of the packages available.
The set of APIs is controlled by Sun Microsystems in cooperation with others through its Java Community Process program. Companies or individuals participating in this process can influence the design and development of the APIs, but Sun retains ownership and control of the APIs. This process has been a subject of controversy.
In 2004, IBM and BEA publicly supported the notion of creating an official open source implementation of Java but so far Sun Microsystems has refused.
Version history
Java Web Start, introduced in Java 2, allows running applications over the web by clicking a desktop icon
The Java language has undergone several changes since JDK 1.0 as well as numerous additions of packages to the standard library:
- 1.0 (1996) — Initial release.
- 1.1 (1997) — Major additions, notably inner classes.
- 1.2 (1998) — Major changes were made to the API (where reflection was introduced) and Sun's JVM (which was equipped with a JIT compiler), but these had little impact on the language itself. This and subsequent releases were rebranded "Java 2", but this had no effect on any software version numbers.
- 1.3 (2000) — minor changes and fixes.
- 1.4 (2002) — As of 2004, the most widely used version . Added the assert keyword.
- 5.0 (2004) — (Originally numbered 1.5, which is still used as the internal version number.) Added a number of significant new language features, some of which have been argued to be modeled on Microsoft's C#, which was itself self-consciously modeled on earlier versions of Java:
- Generics — Provides compile-time type safety for collections and eliminates the need for most typecasts.
- Autoboxing/unboxing — Automatic conversions between primitive types (such as int) and wrapper types (such as Integer).
- Metadata — allows language constructs such as classes and methods to be tagged with additional data, which can then be processed by metadata-aware utilities
- Enumerations — the enum keyword creates a typesafe, ordered list of values (such as Day.monday, Day.tuesday, etc.). Previously this could only be achieved by non-typesafe constant integers or high-overhead constant objects.
- Enhanced for loop — the for loop syntax is extended with special syntax for iterating over each member of an array or Collection, using a construct of the form for (Widget w: box) { System.out.println(w); }. This example iterates over box, assigning each of its items in turn to the variable w, which is then printed to standard output.
In addition to the language changes, much more dramatic changes have been made to the Java class library over the years, which has grown from a few hundred classes in version 1.0 to over three thousand in Java 5.0. Entire new APIs, such as Swing and Java2D, have been introduced, and many of the original 1.0 classes and methods have been deprecated.
Java Runtime Environment
The Java Runtime Environment or JRE is the software required to run any application deployed on the Java platform. End-users commonly utilise a JRE in software packages and plug-ins. Sun also distributes a superset of the JRE called the Java 2 SDK (more commonly known as the JDK), which includes development tools such as the Java compiler, Javadoc and debugger.
Components of the JRE
- Java libraries - which are the compiled byte codes of source developed by the JRE implementor to support application development in Java. Examples of these libraries are:
- The core libraries, which include:
- The integration libraries, which allow the application writer to communicate with external systems. These libraries include:
- User Interface libraries, which include:
- The (heavyweight, or native) Abstract Windowing Toolkit (AWT), which provides GUI components, the means for laying out those components and the means for handling events from those components
- The (lightweight) Swing libraries, which are built on AWT but provide (non-native) implementations of the AWT widgetry
- APIs for audio capture, processing, and playback
- A platform dependent implementation of Java virtual machine (JVM) which is the means by which the byte codes of the Java libraries and third party applications are executed
- Plugins, which enable applets to be run in web browsers
- Java Webstart, which allows Java applications to be efficiently distributed to end users across the internet
- Licensing and documentation
Extensions and related architectures
Extensions and architectures closely tied to the Java programming language include:
- J2EE (Enterprise edition)
- J2ME (Micro-Edition for PDAs and cellular phones)
- JMF (Java Media Framework)
- JNDI (Java Naming and Directory Interface)
- JSML (Java Speech API Markup Language)
- JDBC (Java Database Connectivity)
- JAIN (Java API for Integrated Networks)
- JDMK (Java Dynamic Management Kit)
- Jini (a network architecture for the construction of distributed systems)
- Jiro
- JXTA (open source-based peer-to-peer infrastructure)
- JavaSpaces
- JMI (Java Metadata Interface)
- JMX (Java Management Extensions)
- JSP (JavaServer Pages)
- JSF (JavaServer Faces)
- JNI (Java Native Interface)
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("Hello world!");
}
}
Compilers and JVMs
- GCJ, a Java compiler that comes as part of GCC, the GNU Compiler Collection
- GNU Classpath, GNU's non-compatible replacement for Sun's implementation of the Java class libraries
- The Jakarta Project produces free software in Java, especially tools for building web applications
- Kaffe, a clean room implementation, non-compatible of the Java virtual machine with associated class libraries
- SableVM, a Java Virtual Machine meant to be robust, efficient and portable
- SuperWaba, a Java-like virtual machine, with a minimalistic design suitable for PDA programming
- JUnit, a widely used framework for creating automated unit tests
- JSwat, a standalone, graphical Java debugger
- Spring Framework, a framework for developing Java web applications
- Struts, a framework for developing Java web applications
- IKVM
- Javassist
- Byte Code Engineering Library
- JMangler
- Geronimo, a compatible implementation of J2EE being created within Apache
- BlueJ
Developer Tools
Jarhoo (http://www.jarhoo.com) helps resolve classpath issues by providing details of Jar files containing a class causing NoClassDefFoundError or ClassNotFoundException problems
See also
External links
Sun
General
Historical
Criticism
Third-party software
- beanshell (http://www.beanshell.org) An interpreted implementation of Java, which may be used as a shell or an embedded extension language
- cajo (https://cajo.dev.java.net/) A simple, powerful, and free framework; for transparent, dynamic cooperation, between Java Virtual Machines
- SuperWaba, a Java-like virtual machine (http://www.superwaba.com.br)
- A pure java desktop (http://www.jdistro.com/)
- Java on PocketPC (http://www.vikdavid.com/mobile/)
Java portals, magazines and content sites
- TheServerSide.com (http://www.theserverside.com) A popular Java J2EE portal
- Javalobby (http://www.javalobby.org) A popular forum for Java discussions
- Java.Net (http://www.java.net) A site for Java articles and upcoming projects
- OnJava.com (http://www.onjava.com) An oreilly site for Java with many good Java articles
- IndicThreads.com (http://www.indicthreads.com) An upcoming portal for Java and J2EE
- JavaPro magazine (http://www.javapro.com) A popular java magazine
- JavaWorld magazine (http://www.javaworld.com) A popular java magazine
- Java Developers Journal (http://www.syscon.com/java) Check out the latest java news and user opinions
- JavaRSS.com (http://www.javarss.com) A Java portal of Java websites rich in Java News, Java Articles, Java Blogs, Java Groups and Java Forums.
|