Sun Java Solaris Communities My SDN Account Join SDN
 
White Paper

The Java HotSpot Virtual Machine v1.4.0 Pg.2

 

[Table of Contents/Page 1]  [Page 2]  [Page 3]  [Page 4]  [Page 5]  

Chapter 2
The Java HotSpot VM Architecture
Overview

The Java HotSpot Virtual Machine is Sun Microsystems' VM for the Java platform. It delivers the optimal performance for Java applications using many advanced techniques, incorporating a state-of-the-art memory model, garbage collector, and adaptive optimizer. It is written in an extremely high-level, object-oriented style. It features:

  • Uniform object model

  • Interpreted, compiled, and native frames all use the same stack

  • Pre-emptive multithreading based on native threads

  • Accurate generational and compacting garbage collection

  • Ultra-fast thread synchronization

  • Dynamic deoptimization and aggressive compiler optimizations

  • System-specific runtime routines generated at VM startup time

  • Compiler interface supporting parallel compilations

  • Run-time profiling focuses compilation effort only on "hot" methods

In the Java 2, Standard Edition SDK version 1.4.0 release there are two flavors of the VM--a client-side offering, and a VM tuned for server applications. These two solutions share the Java HotSpot runtime environment code base, but use different compilers suited to the distinctly different performance characteristics of clients and servers. These differences include the compilation inlining policy and heap defaults.

The Java 2, Standard Edition SDK contains both of the above systems in the distribution and developers choose which system they want by specifying -client or -server.

The Server and the Client VMs are similar, except that the Server VM has been specially tuned to maximize peak operating speed. It is intended for executing long-running server applications, for which having the fastest possible operating speed is generally more important than having a fast start-up time or smaller runtime memory footprint.

The Client VM compiler serves as an upgrade for both the "classic" virtual machine and the just-in-time (JIT) compilers used by previous versions of the Java SDK. The Client VM offers improved runtime performance for applications and applets. The Java HotSpot Client VM has been specially tuned to reduce application start-up time and memory footprint, making it particularly well suited for client environments. In general, the client system is better for GUIs.

The Client VM compiler doesn't try to execute many of the more complex optimizations performed by the compiler in the Server VM, but in exchange requires less time to analyze and compile a piece of code. This means the Client VM can start up faster and requires a smaller memory footprint.

Figure 2-2: Figure 2: The Java HotSpot Client VM, on the left, and the Java HotSpot Server VM, on the right, use different compiler but otherwise interface to the same virtual machine, using the same garbage collection (GC) routine, interpreter, thread and lock subsystems, and so on.

The Server VM contains an advanced adaptive compiler that supports many of the same types of optimizations performed by optimizing C++ compilers, as well as some optimizations that can't be done by traditional compilers, such as aggressive inlining across virtual method invocations. This is a competitive and performance advantage over static compilers. Adaptive optimization technology is very flexible in its approach, and typically outperforms even advanced static analysis and compilation techniques.

Both solutions deliver extremely reliable, secure and maintainable environments, to meet the demands of today's enterprise customers.

Memory Model
Handleless Objects

In previous versions of the Java virtual machine, such as the "Classic" VM, indirect handles are used to represent object references. While this makes relocating objects easier during garbage collection, it represents a significant performance bottleneck, because accesses to the instance variables of Java programming language objects require two levels of indirection.

In the Java HotSpot VM no handles are used by Java code. Object references are implemented as direct pointers. This provides C-speed access to instance variables. The garbage collector is then responsible for finding and updating all references to an object in-place when the object is relocated during memory reclamation.

Two-Word Object Headers

The Java HotSpot VM uses a two machine-word object header as opposed to three words as in the Classic VM. Since the average Java object size is small, this has a significant impact on space consumption--approximately an 8% savings in heap size for typical applications. The first header word contains information such as the identity hash code and GC status information. The second is a reference to the object's class. Only arrays have a third header field, for the array size.

Reflective Data are Represented as Objects

Classes, methods, and other internal reflective data are represented directly as objects on the heap (although those objects may not be directly accessible to Java technology-based programs). This not only simplifies the VM internal object model, but also allows classes to be collected by the same garbage collector used for other Java programming language objects.

Native Thread Support, Including Preemption and Multiprocessing

Per-thread method activation stacks are represented using the host operating system's stack and thread model. Both Java programming language methods and native methods share the same stack, allowing fast calls between the C and Java programming languages. Fully preemptive Java programming language threads are supported using the host operating system's thread scheduling mechanism.

A major advantage of use of native OS threads and scheduling is the ability to transparently take advantage of native OS multiprocessing support. Because the Java HotSpot VM is designed to be insensitive to race conditions caused by preemption and/or multiprocessing while executing Java programming language code, the Java programming language threads will automatically take advantage of whatever scheduling and processor allocation policies the native OS provides.

Back to Top

Garbage Collection
Background

While the fundamental GC algorithms used by the HotSpot virtual machine have not changed significantly since J2SE 1.3.1, there have been several subtle improvements. One of the most important is in the area of generation sizing. J2SE version 1.4 features improved heuristics for selecting the most efficient settings which can have dramatic effects on GC throughput.

A major attraction of the Java programming language for programmers is that it is the first mainstream programming language to provide built-in automatic memory management, or garbage collection (GC). In traditional languages, dynamic memory allocation is done using an explicit allocate/free model. In practice, this turns out to be not only one of the largest sources of memory leaks, program bugs, and crashes in programs written in traditional languages, but also a performance bottleneck as well as a major impediment to modular, reusable code. (Determining free points across module boundaries is often nearly impossible without explicit and hard-to-understand cooperation between modules.) In the Java programming language, garbage collection is also an important part of the "safe" execution semantics required to support the security model.

A garbage collector automatically handles "freeing" of unused object memory behind the scenes by only reclaiming an object when it can prove that the object is no longer accessible to the running program. Automation of this process completely eliminates not only the memory leaks caused by freeing too little, but also the program crashes and hard-to-find reference bugs caused by freeing too much.

Traditionally, garbage collection has been considered an inefficient process that impeded performance, relative to an explicit-free model. In fact, with modern garbage collection technology, performance has improved so much that overall performance is actually substantially better than that provided by explicit freeing of objects.

The Java HotSpot Garbage Collector

The Java HotSpot VM contains an advanced garbage collector. In addition to including the state-of-the-art features described below, it takes maximum advantage of the clean, object-oriented design to provide a high-level garbage collection framework that can easily be instrumented, experimented with, or extended to use new collection algorithms.

Below, the major features of the Java HotSpot garbage collector are presented. Overall, the combination of techniques used is better both for applications where the highest possible performance is needed, and for long-running applications, where memory leaks and memory inaccessibility due to fragmentation are highly undesirable. The Java HotSpot VM not only provides state-of-the-art garbage collector performance, but also can provide full memory reclamation, while eliminating memory fragmentation.

Accuracy

The Java HotSpot garbage collector is a fully accurate collector. In contrast, many other garbage collectors are conservative or partially-accurate. While conservative garbage collection can be attractive because it is very easy to add to a system without garbage collection support, it has certain drawbacks. In general, conservative garbage collectors are prone to memory leaks, disallow object migration, and can cause heap fragmentation.

A conservative collector does not know for sure where all object references are located. As a result, it must be conservative by assuming that memory words that appear to refer to an object are in fact object references. This means that it can make certain kinds of mistakes, such as confusing an integer for an object pointer. Memory cells that look like a pointer are regarded as a pointer--and GC becomes "inaccurate." This has several negative impacts. First, when such mistakes are made, which in practice is not very often, memory leaks can occur unpredictably in ways that are virtually impossible for application programmers to reproduce or debug. Second, since it might have made a mistake, a conservative collector must either use handles to refer indirectly to objects--decreasing performance--or avoid relocating objects, because relocating handleless objects requires updating all the references to the object. This cannot be done if the collector does not know for sure that an apparent reference is a real reference. The inability to relocate objects causes object memory fragmentation and, more importantly, prevents use of the advanced generational copying collection algorithms described below.

Because the Java HotSpot collector is fully accurate, it can make several strong design guarantees that a conservative collector cannot make:

  • All inaccessible object memory can be reclaimed reliably.

  • All objects can be relocated, allowing object memory compaction, which eliminates object memory fragmentation and increases memory locality.

    An accurate garbage collection mechanism avoids accidental memory leaks, enables object migration, and provide for full heap compaction. The garbage collection mechanism in the Java Hotspot VM scales well to very large heaps.

Generational Copying Collection

The Java HotSpot VM employs a state-of-the-art generational copying collector, which provides two major benefits:

  • Major increases in both allocation speed and overall garbage collection efficiency for most programs, compared to non-generational collectors.

  • A corresponding decrease in the frequency and duration of user-perceivable garbage collection "pauses."

A generational collector takes advantage of the fact that in most programs the vast majority of objects (often greater than 95%) are very short-lived (for example, they are used as temporary data structures). By segregating newly created objects into an object "nursery," a generational collector can accomplish several things. First, because new objects are allocated contiguously in stack-like fashion in the object nursery, allocation becomes extremely fast, since it involves merely updating a single pointer and performing a single check for nursery overflow. Secondly, by the time the nursery overflows, most of the objects in the nursery are already "dead," allowing the garbage collector to simply move the few surviving objects elsewhere, and avoid doing any reclamation work for dead objects in the nursery.

Mark-Compact "Old Object" Collector

Although the generational copying collector collects most dead objects efficiently, longer-lived objects still accumulate in the "old object" memory area. Occasionally, based on low-memory conditions or programmatic requests, an old-object garbage collection must be performed. The Java HotSpot VM can use a standard mark-compact collection algorithm, which traverses the entire graph of live objects from its "roots," and then sweeps through memory compacting away the gaps left by dead objects. By compacting gaps in the heap, rather than collecting them into a freelist, memory fragmentation is eliminated, and old object allocation is streamlined by eliminating freelist searching.

Incremental "Pauseless" Garbage Collector

The mark-compact collector does not eliminate all user-perceivable pauses. User-perceived GC pauses occur when "old" objects (objects that have "lived" for a while in machine terms) need to be garbage collected, and these pauses are proportional to the amount of live object data that exists. This means that the pauses can become arbitrarily large as more data is manipulated, which is a very undesirable property for server applications, animation or other soft-real time applications.

The Java HotSpot VM provides an alternative old-space garbage collector to solve this problem. This collector is fully incremental, eliminating user-detectable garbage collection pauses. This incremental collector scales smoothly, providing relatively constant pause times even when extremely large object data sets are being manipulated. This provides excellent behavior for:

  • Server applications, especially high-availability applications

  • Applications that manipulate very large "live" object data sets

  • Applications where all user-noticeable pauses are undesirable, such as games, animation, or other highly interactive applications.

The pauseless collector works by using an incremental old space collection scheme referred to academically as the "train" algorithm. This algorithm breaks up old-space collection pauses into many tiny pauses (typically less than ten milliseconds) that can be spread out over time so that the program virtually never appears to pause to a user. Since the train algorithm is not a hard-real time algorithm, it cannot guarantee an upper limit on pause times, however, in practice much larger pauses are extremely rare, and are not caused directly by large data sets.

The pauseless collector also has the highly desirable side-benefit of producing improved memory locality. This happens because the algorithm works by attempting to relocate groups of tightly 'coupled' objects into regions of adjacent memory, providing excellent paging and cache locality properties for those objects. This can also benefit highly multi-threaded applications that operate on distinct sets of object-data.

Back to Top

64-bit Architecture

Previous releases of the Java HotSpot VM were limited to addressing 4 gigabytes of memory--even on 64-bit operating systems such as Solaris OE. While 4 gigabytes is a lot for a desktop system, modern servers can contain far more memory. For example, the new SunFire 15K server comes in a standard configuration with 288 gigabytes of memory. With a 64-bit JVM, Java applications can now utilize the full memory of such a system.

There are several classes of applications where using 64-bit addressing can be very useful. For example, applications that store very large data sets in memory. Applications can now avoid the overhead of paging data from disk, or extracting data from a RDBMS. This can lead to dramatic performance improvements in applications of this type.

The Java HotSpot Server VM is now 64-bit safe, and the Server VM includes support for both 32-bit and 64-bit operations, and users can select either 32-bit or 64-bit operation by using command-line flags -d32 or -d64, respectively. Users of the Java Native Interface will need to recompile their code to be able to run it on the 64-bit VM.

Object packing functionality has been added to minimize the wasted space between data types of different sizes. This is primarily a benefit in 64-bit environments, but offers a a small advantage even in 32-bit VMs.

    For example:
public class Button {
 char shape;
 String label;
 int xposition; 
 int yposition;
char foo;
int joe;
object mike;
char fum;
}

    This would waste space between: foo and joe (3 bytes to pad to an int boundary) joe and mike (4 bytes on a 64-bit VM to pad to a pointer boundary) Now, the fields are reordered to look like this:

...
object mike;
int joe;
char foo;
char fum;
...

    In this example, no memory space is wasted.
Ultra-Fast Thread Synchronization

The Java programming language allows for use of multiple, concurrent paths of program execution--threads. The Java programming language provides language-level thread synchronization, which makes it easy to express multi-threaded programs with fine-grained locking. Previous synchronization implementations were highly inefficient relative to other micro-operations in the Java programming language, making use of fine-grain synchronization a major performance bottleneck.

The Java HotSpot VM incorporates a breakthrough in thread synchronization implementation that boosts synchronization performance by a large factor. As a result, synchronization performance becomes so fast that it is not a significant performance issue for the vast majority of real-world programs.

In addition to the space benefits mentioned in the Memory Model section, the synchronization mechanism provides its performance benefits by providing ultra-fast, constant-time performance for all uncontended synchronizations, which dynamically comprise the great majority of synchronizations.

The Java HotSpot VM provides a leaner, speedier thread-handling capability that is designed to scale readily for use in large, shared-memory multiprocessor servers.

New I/O APIs

The new I/O (NIO) APIs introduced in version 1.4 provide new features and improved performance in the areas of buffer management, scalable network and file I/O, character-set support, and regular-expression matching. These new APIs are supported in both client and server compilers. With new I/O, developers can now write ultra-scalable, high-performance server applications such as Web, application, file, and database servers. They can also write compute-intensive scientific, technical, and graphics applications that require fast access to large quantities of data. I/O operations that previously required programming in C or C++ can now be performed using Java, but with the performance of a native C or C++ application.

  • The new network I/O package dramatically increases the number of simultaneous connections that a server can handle by removing the need to dedicate one thread to every open connection.

  • New File I/O supports read, write, copy, and transfer operations that are up to twice as fast as the current file I/O facilities. It also supports file locking, memory-mapped files, and multiple concurrent read/write operations.

Back to Top

[Table of Contents/Page 1]  [Page 2]  [Page 3]  [Page 4]  [Page 5]