It doesn't explore every reference until it has to
According to the JVM specification the bootstrap loader is specified to works as follows:
5.3.1 Loading Using the Bootstrap Class Loader The following steps are
used to load and thereby create the
nonarray class or interface C denoted
by N using the bootstrap class loader.
First, the Java virtual machine
determines whether the bootstrap class
loader has already been recorded as an
initiating loader of a class or
interface denoted by N. If so, this
class or interface is C, and no class
creation is necessary.
Otherwise, the Java virtual machine
performs one of the following two
operations in order to load C:
1: The Java virtual machine searches for a purported
representation of C in a
platform-dependent manner. Note that
there is no guarantee that a purported
representation found is valid or is a
representation of C.
Typically, a class or interface will be represented using a file in a
hierarchical file system. The name of
the class or interface will usually be
encoded in the pathname of the file.
This phase of loading must detect the following error:
- If no purported representation of C is found, loading
throws an instance of
NoClassDefFoundError or an instance of
one of its subclasses.
Then the Java virtual machine attempts to derive a class denoted by
N using the bootstrap class loader
from the purported representation
using the algorithm found in Section
5.3.5. That class is C.
2: The bootstrap class loader can delegate the loading of C to some
user-defined class loader L by passing
N to an invocation of a loadClass
method on L. The result of the
invocation is C. The Java virtual
machine then records that the
bootstrap loader is an initiating
loader of C (§5.3.4).
Note the use of platform-dependent manner. This means that when searching for a particular instance of a class the JVM is required to explore a file system of some kind. In the case of your application it is a bunch of JARs.
As it searches through the classpath the JVM makes it's own internal index (probably an efficient Map) based on the JAR name and the paths it has encountered during the dynamic linking process. This index grows as more JARs are explored to resolve all references, but may not include all JARs unless not exploring them would cause a
This loading process is helped by the fact that the JAR file specification provides a facility for /META-INF/INDEX.LIST which acts as a trusted index of class definitions within the JAR.
An interesting side-effect of this process is that duplicate class definitions with the same name and package but different method signatures won't necessarily be detected until execution takes place (