Among commercially popular programming languages, the Java language distinguishes itself by running on a Java virtual machine (JVM). This means that compiled programs are expressed in a special, platform-independent format, rather than in the format of the machine they are running on. This format differs from traditional executable program formats in a number of important ways.
In particular, a Java program, unlike one written in C or C++, isn't a single executable file, but instead is composed of many individual class files, each of which corresponds to a single Java class.
Additionally, these class files are not loaded into memory all at once, but rather are loaded on demand, as needed by the program. The ClassLoader is the part of the JVM that loads classes into memory.
The Java ClassLoader, furthermore, is written in the Java language itself. This means that it's easy to create your own ClassLoader without having to understand the finer details of the JVM.
If the JVM has a ClassLoader, then why would you want to write another one? Good question. The default ClassLoader only knows how to load class files from the local filesystem. This is fine for regular situations, when you have your Java program fully compiled and waiting on your computer.
But one of the most innovative things about the Java language is that it makes it easy for the JVM to get classes from places other than the local hard drive or network. For example, browsers use a custom ClassLoader to load executable content from a Web site.
There are many other ways to get class files. Besides simply loading files from the local disk or from a network, you can use a custom ClassLoader to:
- Automatically verify a digital signature before executing untrusted code
- Transparently decrypt code with a user-supplied password
- Create dynamically built classes customized to the user's specific needs
Anything you can think of to write that can generate Java bytecode can be integrated into your application.
If you've ever used the appletviewer included in the JDK or any Java-enabled browser, you've almost certainly used a custom ClassLoader.
When Sun initially released the Java language, one of the most exciting things was watching how this new technology executed code that it had loaded on the fly from a remote Web server. (This was before we'd realized something more exciting -- that Java technology provided a great language for writing code.) There was just something thrilling about it executing bytecode that had just been sent through an HTTP connection from a distant Web server.
What made this feat possible was the ability of the Java language to install a custom ClassLoader. The appletviewer contains a ClassLoader that, instead of looking in the local filesystem for classes, accesses a Web site on a remote server, loads the raw bytecode files via HTTP, and turns them into classes inside the JVM.
The ClassLoaders in browsers and appletviewers do other things as well: they take care of security and keep different applets on different pages from interfering with each other.
Echidna by Luke Gorrie is an open-source software package that allows you to safely run multiple Java applications inside a single virtual machine. (See Further reading and references. ) It uses a custom ClassLoader to prevent the applications from interfering with each other, by giving each application its own copy of the class files.
After you have a good idea of how a ClassLoader works and how one is written, we'll create our own custom ClassLoader called CompilingClassLoader (CCL). CCL compiles our Java code for us, in case we didn't bother to do it ourselves. It's basically like having a simple "make" program built directly into our run-time system.
Note: Before we go any further, it's important to note that some aspects of the ClassLoader system have been improved in JDK version 1.2 (also known as the Java 2 platform). This tutorial was written with JDK versions 1.0 and 1.1 in mind, but everything in it works under later versions as well.
ClassLoader changes in Java 2 describes the changes in Java version 1.2 and provides details for modifying our ClassLoader to take advantage of these changes.