What is Java, Really?
Java conjures up a variety of images for computer users everywhere. Some picture flying heads and cartoonish figures that wave from web pages. Others remember segmentation faults and hung Netscapes. Most people are left staring at the steaming cup-o'-joe icon, having no idea what it all really means. This article will discuss what exactly Java is, and where it fits in the big picture of computing.
The Java programming language is roughly similar to C++, Objective C and Smalltalk, with some features removed and a few features added:
It is procedural, like C, as opposed to functional like Lisp.
It is object-oriented, like C++. It supports classes, single class inheritance, multiple interface inheritance, access protection and exceptions. It does not support operator overloading or templates (though it may support template-like constructs in the future).
All casts are dynamic and safe; it's impossible to cast an object to an inappropriate type.
Everything in Java is class-oriented. There is no global scope, there are no global variables, and there are no explicit function pointers.
Arrays of arbitrary dimension are supported and act like objects.
It supports threads and provides synchronization primitives. Threads, sometimes called lightweight processes, allow several separate execution paths to run concurrently through a program. Synchronization primitives ensure that separate tasks are performed in the correct order.
It supports modules, so it doesn't need a preprocessor. There are no #include directives as the equivalent functionality is built into the languagex), no macros, no #define, etc.
It supports garbage-collection, and there is no support for explicit deallocation. This simplifies programming dramatically and eliminates all memory allocation errors.
All objects implicitly use reference semantics, which roughly means every object acts like a pointer, but used as if it were a value. All base types (int, char, etc.) use value semantics.
Java is safe, meaning it is impossible to: de-reference a pointer outside a segment; use memory that has been deallocated; or use an object as the wrong type. A Java program will never cause a segmentation fault (actually, the Java interpreter does have a few bugs that can result in an application crashing, but these are being fixed).
Java comes bundled with a standard library called the Java API (Application Program Interface) that provides:
Basic file input and output
Networking, particularly TCP/IP, UDP, and HTTP
Basic dynamic container classes like Vector, Dictionary, etc.
Graphics and GUI programming
Another important component of the Java system is the compiler. A Java compiler translates source files (e.g., Foo.java) into one or more class files (e.g., Foo.class). The .class files correspond roughly to the .o (or .obj) files in C, but there is one crucial difference: while .o files contain machine-specific instructions, .class files contain only a generic pseudo-assembly-code called Bytecode that is uniform across all platforms. To enable this, every platform that supports Java must have a Java runtime that will interpret and execute Java Bytecode.
The underlying Bytecode to which Java compiles is described under Sun's Java Virtual Machine (or JVM) specification (java.sun.com/doc/vmspec/html/vmspec-1.html) A Java runtime emulates a JVM, so that it can run the Java Bytecode contained within .class files. The JVM is a key component to Java's ubiquity; rather than require that every individual application support multiple platforms, developers need only write one version of a program, and are assured that it will run everywhere. The only program that needs to be ported across multiple platforms is the Java runtime. Despite Java's youth, most major platforms are supported.
Let's now take a moment to trace the steps involved in letting you see waving animated characters within your web browser.
A programmer on the Web somewhere writes a Java program, and converts .java source files into .class files using a java compiler. This programmer puts a reference to these .class files within an <APPLET> tag in her web page.
You point your browser to her web page, and your browser sees the <APPLET> tag pointing to the .class files. Your browser then downloads her .class files over the net.
Your browser starts up its Java runtime subsystem and begins executing the .class files that it downloaded.
At this point, you might be wondering what prevents a malicious programmer from doing horrible things to your computer while the comforting cartoonish character distracts you from the sound of your hard drive as it's being reformatted. The answer lies in the Java SecurityManager. This class, a part of the standard, implements a security policy for all untrusted programs. Here, untrusted programs are those that are downloaded over the net. In the current release of Netscape, the SecurityManager that the Java runtime uses does not allow untrusted Java programs to read or write files, nor does it allow them to make network connections anywhere except to the host from which the program came. This, then, forms a sort of sand box in which the Java program is confined.
Another key facet of the Java security model is the Bytecode Verifier. The Bytecode Verifier checks all incoming programs to make sure that they satisfy some basic safety constraints (e.g., every pointer cast is a safe one, there can be no stack overflows, etc.). This prevents malicious programmers from creating bad .class files by programming Java Bytecode by hand in an effort to circumvent the safety features of the Java language. If your Netscape downloads a .class file that fails to pass the verification stage, it will simply refuse to run the code.
Most people view Java as the programming language of the Web. Though Java certainly serves well in this regard, it is actually much more general; it is appropriate for stand-alone, non-Web programming as well. You can write Java programs that can be run outside of a web browser, and as trusted programs they can do everything a C or C++ program might do, such as access the file-system. In fact, in the Linux development pre-2.0 kernels there is support for the Java binary format. This support means that you can run Java Bytecode programs just as you would run ELF- or a.out-format executables from the command line, without explicitly invoking a Java runtime. The great advantage of writing programs in Java is that they are immediately portable across a wide variety of platforms and architectures.
One problem with current Java implementations is speed; performance is many times slower than C under most current implementations. This is because the Java Bytecode is interpreted, unlike native assembly code compiled from C programs which is run directly by the processor. The speed problem is being mitigated, however, by the development of so-called “Just-In-Time” compilers. These compilers (which are actually part of the Java runtime system) compile .class files into native assembly code on the fly. In so doing, they can speed up Java programs many times. Furthermore, since they only compile classes as they execute, the typical initial delay associated with traditional compilation is eliminated. As these compilers mature, we can expect the performance hit associated with Java to disappear.
At this point, you may want to know how you can become Java-enabled. If you simply want to run Java applets on your machine, (that is, Java programs transferred over the Web) you can do so using the latest Netscape beta, available from www.netscape.com/. If you'd like to begin experimenting with programming in Java, or running non-browser stand-alone Java programs, you can do so with the free Linux port of the Java Development Kit (JDK). Point your browser at java.blackdown.org/java-linux/Information.html to find out where to get this. If you'd like an alternative to the Java compiler included in the JDK, there is EspressoGrinder, a drop-in replacement for the JDK compiler. EspressoGrinder is written in Java, and thus can be run anywhere that a Java runtime has been ported. You can get it at wwwipd.ira.uka.de/~espresso/. If you'd like more information on Java, the JDK, and general Java happenings, check out Sun's site at: www.javasoft.com/java.sun.com/devcorner.html. A Java FAQ is available from sunsite.unc.edu/javafaq/javafaq.html.
The political and economic significance of Java is enormous, especially for Linux developers. Because of the high degree of virtualization in the JVM, developers are free to create their applications on platforms other than those that they target. Thus, it is now possible to use your Linux system to develop Java applications that can effortlessly tap into the popularity of Windows, Macintosh, HP-UX or SGI machines, to name a few. Furthermore, Linux will undoubtedly be able to reap the benefits of applications written under other platforms for exactly the same reasons. Overall, we can expect Java to usher in a new era of software interoperability, empowering developers and users alike on all platforms.
Rudi Cilibrasi (email@example.com) has been programming computers for over a decade; he works as a software consultant, specializing in Java, C++, and Linux.
- March 2015 Issue of Linux Journal: System Administration
- High-Availability Storage with HA-LVM
- DNSMasq, the Pint-Sized Super Dæmon!
- Localhost DNS Cache
- Real-Time Rogue Wireless Access Point Detection with the Raspberry Pi
- Days Between Dates: the Counting
- You're the Boss with UBOS
- The Usability of GNOME
- Multitenant Sites
- Linux for Astronomers