How The JVM Locates, Loads, and Runs Libraries: Class Loaders Are The Key To Understanding How The JVM Executes Programs
How The JVM Locates, Loads, and Runs Libraries: Class Loaders Are The Key To Understanding How The JVM Executes Programs
The Class-Loader Hierarchy can load—or already A sort of child of the bootstrap class loader is
the extension class loader, which loads the classes
The class loaders in the JVM are organized into has loaded—the from the extension directories (explained in a
a tree hierarchy, in which every class loader
has a parent. Prior to trying to locate and load a
required class. moment). These classes may be used to specify
machine-specific configuration such as locales,
class, a good practice for a class loader is to check security providers, and such. The locations of
whether the class’s parent in the hierarchy can the extension directories are specified via the
load—or already has loaded—the required class. This helps java.ext.dirs system property, which on my machine is
avoid doing double work and loading classes repeatedly. As a set to the following:
rule, the classes of the parent class loader are visible to the
children but are not visible otherwise. This structure, which /Users/shelajev/Library/Java/Extensions:/Library/
is based on delegation and visibility of the classes, allows for Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/
Home/jre/lib/ext:/Library/Java/Extensions:/Network/
separation of the responsibilities of the class loaders in the
Library/Java/Extensions:/System/Library/Java/
hierarchy and makes the class loaders responsible for loading Extensions:/usr/lib/java
classes from a specific location only.
Let’s look at this hierarchy of class loaders in a Java appli- By changing the value of this property, you can change
cation and explore what classes they typically load. At the which additional libraries are loaded into the JVM process.
root of the hierarchy, Java is the bootstrap class loader. It Next comes the system class loader, which loads the
loads the system classes required to run the JVM itself. You application classes and the classes available on the class-
can expect all the classes that were provided with the JDK
31
ORACLE.COM/JAVAMAGAZINE //////////////////////////////// NOVEMBER/DECEMBER 2015
//libraries /
path. Users can specify the classpath using the second JAR file. Naturally, if the class isn’t
-cp property. Many security found anywhere on the classpath, the
Both the extension class loader and the system features rely on the ClassNotFound exception will be thrown.
class loader are of the URLClassloader type and
behave in the same way: delegating to the par-
class-loader hierarchy Usually, relying on the order of directo-
ries in the classpath is a fragile practice, so
ent first, and only then finding and resolving the for permission checks. instead the developer can add the classes to
required classes themselves, if need dictates. -Xbootclasspath to ensure that they will be
The class-loader hierarchy of web applica- loaded first. There’s nothing in particular wrong
tions is a bit more complicated. Because multiple with this approach, but maintaining a proj-
applications can be deployed simultaneously to an applica- ect that relies on a polluted boot classpath requires work.
tion server, they need to be able to distinguish their classes Intuition about where the classes are loaded from will be
from each other. So, every web application uses its own class broken, and everyone will be confused. A better practice is
loader, which is responsible for loading its libraries. Such to resolve the confusion at its root and figure out why there
isolation ensures that different web applications deployed to are multiple classes with the same name on the classpath.
a single server can have different versions of the same library Maybe upgrading some dependency version, cleaning the
without conflicts. So the application server automatically caches, or running a clean build will be enough to get rid of
provides every web application with its own class loader, the duplicates.
which is responsible for loading the application’s libraries.
This arrangement works because the web application class Resolution, Linking, and Verification
loader will try to locate the classes packaged in the applica- After a class is located and its initial in-memory represen-
tion’s WAR file first, rather than first delegating the search to tation created in the JVM process, it is verified, prepared,
the parent class loader. resolved, and initialized.
■■ Verification makes sure that the class is not corrupted and
Finding the Right Class is structurally correct: its runtime constant pool is valid,
In general, if multiple classes with the same fully qualified the types of variables are correct, and the variables are
name are available to the JVM, the conflict resolution strat- initialized prior to being accessed. Verification can be
egy is simple and straightforward: the first appropriate class turned off by supplying the -noverify option. If the JVM
wins. The URLClassloader, which most of the class loaders process does not run potentially malicious code, strict
extend from, will traverse the directories in the order they verification might not be required. Turning off the verifi-
are given on the classpath and load the first class it finds cation can speed up the startup of the JVM. Another
that has requested the class name. benefit is that some classes, especially those generated
The same goes for JAR files that share the same name. The on the fly by various tools, can be valid and safe for the
JAR files will be scanned in the order in which they appear in JVM but unable to pass the strict verification process. In
the classpath, not according to their names. If the first JAR order to use such tools, the developer should disable this
file contains an entry for the required class, the class will be verification, which is often acceptable to do in a develop-
loaded. If not, the classpath scan will continue and reach the ment environment.
32
ORACLE.COM/JAVAMAGAZINE //////////////////////////////// NOVEMBER/DECEMBER 2015
//libraries /
■■ Preparation of a class involves initializing its static fields to that uses the Unsafe API must rely on the Reflection API to
the default values for their respective types. (After prepa- read the reference from a private field.
ration, fields of type int contain 0, references are null, and
so forth.) Conclusion
■■ Resolution of a class means checking that the symbolic When you’re developing a library or a framework, as a rule,
references in the runtime constant pool actually point you don’t have to worry about any issues with class load-
to valid classes of the required types. The resolution of a ing. It is a dynamic process that happens at runtime, so you
symbolic reference triggers loading of the referenced rarely need to influence it. Also, modifying the class-loading
class. According to the JVM specification, this resolution scheme rarely benefits a typical Java library.
process can be performed lazily, so it is deferred until the However, if you create a system of modules or plugins that
class is used. are intended to be isolated from each other, enhancing the
■■ Initialization expects a prepared and verified class. It runs class-loading scheme might be a good idea. Just remember
the class’s initializer. During initialization, the static fields that custom class loaders, being a fundamental force influ-
are initialized to whatever values are specified in the code. encing all the classes, can introduce hard-to-spot bugs into
The static initializer method that combines the code from literally any part of your application. So take extra care when
all the static initialization blocks is also run. The initializa- designing your own class-loading functionality.
tion process should be run only once for every loaded class, In this article, we looked at how the JVM loads classes into
so it is synchronized, especially because the initialization the runtime, at the hierarchical model of class loaders Java
of the class can trigger the initialization of other classes uses, and the hierarchy model of a typical Java application.
and should be performed with care to avoid deadlocks. All in all, even if you don’t fight class-loading issues or
More detail on how the JVM performs the loading, linking, create plugin architectures every day, understanding class
and initializing of classes is explained in Chapter 5 of the Java loading helps you to understand what is happening in your
Virtual Machine Specification. application. It also provides insight into how several Java
tools work. And it really demonstrates the benefits of keeping
Other Considerations About Class Loaders your classpath clean and up to date. </article>
The class-loading model is the central piece of the dynamic
operations of the Java platform. Not only does it allow for Oleg Šelajev (@shelajev) is an engineer, author, speaker, lecturer,
dynamic location and linking of classes at runtime, but and developer advocate at ZeroTurnaround. He enjoys spending
it also provides an interface for various tools to hook into time tinkering with Clojure, Git, and MacVim and is pursuing a PhD
the application. in dynamic software updates and code evolution at the University
In addition, many security features rely on the class-loader of Tartu.
hierarchy for permission checks. For example, the famous
method sun.misc.Unsafe.getUnsafe() successfully
returns an instance of the Unsafe class if it is called from a LEARN MORE
class that was loaded by the bootstrap class loader. Because • Information on controlling class loaders
only system classes are returned by this loader, every library • Class loaders in the JVM Specification
33
ORACLE.COM/JAVAMAGAZINE //////////////////////////////// NOVEMBER/DECEMBER 2015