Sponsored Link •
When you start a Java application, you give the name of a class that has a
main() method to a JVM. The JVM starts executing
Java at the indicated
main() method, and the application
is off and running.
Each application lives inside its very own "instance" of the JVM, with memory areas that are private just to that application. Although different threads of the same application can all access a common heap, for example, threads in one Java application can't directly access the heap in another Java application. Each Java application gets its own Java virtual machine.
Inside a JVM, each class loader (be it primordial or object) gets its
own name space. A name space is simply the set of fully
qualified names of all the classes and interfaces that a class loader
has loaded so far. A fully qualified name of a class is the
name of its package, plus a dot, plus its simple name. For example, the
fully qualified name of the
Hashtable class from the
java.util package is
Within a single name space, all fully qualified names are unique. Two different name spaces, however, can contain identical fully qualified names. This architecture enables a single Java application to load and use two (or more) different classes that have the same fully qualified name. So long as those like-named classes are loaded by different class loaders, which will cause the classes to be placed into different name spaces, the Java application will be able to load and use them.
As an example, Figure 1 shows a snapshot of two name spaces in a single
Java application. Two fully qualified names are common to both name
Mouse. The upper
name space contains two other fully qualified names (
Cat) that don't appear in the lower name space. Likewise, the lower name space contains two fully
qualified names (
Keyboard) that don't appear in the upper name space. Within each name space, however, all names are unique.
Figure 1. Two name spaces
All of this is fine and good, but begs the question: How are the names in a name space related to the actual types being named? When a JVM loads a type (class or interface), it parses and extracts information about the type from a class file. It places this information (in some data structure devised by the people who implement the JVM) into a logical area of the JVM's memory called the method area. So when the JVM loads a class, a chunk of type data is added to the method area and a fully qualified name is inserted into a name space. Every fully qualified name in every name space is associated with a chunk of data in the method area that defines that named type.
For example, Figure 2 shows the relationship between names
java.lang.Object) in the name
spaces of the previous example and type data in the method area. One
fully qualified name that both name spaces contain is
java.lang.Object. In the case of this name, both entries (one in each name space) are associated with the same chunk of type data in the method area.
By contrast, although both name spaces also
contain the fully qualified name
Mouse, each entry (one in
each name space) is associated with a different chunk of type data in
the method area. In the upper name space, the name
is associated with a chunk of type data that describes a small, furry
animal with a pink nose. In the lower name space, the name
Mouse is associated with a chunk of type data that
describes a device you attach to your computer.
Figure 2. Names and definitions
Dynamic linking and name spaces
When you compile a Java program, you get one class file for each type (class or interface) you define in source code. The class file is an intermediate compiled binary format for the type. Class files, which haven't been linked, contain symbolic references to other types in a list called the constant pool. At runtime, the JVM dynamically links the Java application by resolving the symbolic references contained in the constant pools of class files. This process is called constant pool resolution.
Name spaces in the JVM arise from a simple rule that all JVMs must follow when they resolve the symbolic references contained inside class files. Sometimes, an entry in a constant pool may refer symbolically to a type that hasn't yet been loaded. When such entries are resolved, the JVM must load the referred-to type. Because all types must be loaded by a class loader, the JVM must at that point decide which class loader to ask to load the type.
To choose a class loader, the JVM uses this simple rule:
The Resolution Rule - The JVM loads referenced types via the same class loader that loaded the referencing type.