Create a custom Java 1.2-style ClassLoader - JavaWorld March 2000
Tutorial Details:
Create a custom Java 1.2-style ClassLoader
Create a custom Java 1.2-style ClassLoader
By: By Ken McCrary
The Java 1.2 delegation model simplifies class-loading design and implementation
evelopers have two well-known reasons for building custom ClassLoader s: providing support for a new class repository and partitioning user code in a server. The applet ClassLoader is an example of the former. It introduces the ability to load classes from an HTTP server. The latter purpose -- partitioning user code in a server -- is less frequent. For example, consider a servlet engine responsible for running servlets created by several developers. Those developers may be unaware of each other, as in a commercial Web-hosting environment, and they will want their Java code to execute independently of any other code using the servlet runner. A custom ClassLoader can maintain a separate ClassLoader for each developer's servlet. Since a class is identified in a Java virtual machine (JVM) by its full name and the ClassLoader that loaded it, classes loaded by a different ClassLoader are effectively separated. This use of custom ClassLoader s provides for multiple pseudoapplications to run concurrently in the JVM.
Java 1.1 custom ClassLoader responsibilities
The earlier Java 1.1-style custom ClassLoader s let you load Java classes from all sorts of interesting places. (For information regarding Java 1.1-style custom ClassLoader s, see Resources .) However, this capability carried the price of complexity. The abstract class java.lang.ClassLoader required a custom ClassLoader to implement a single method: loadClass() . Nothing difficult about implementing a single method -- pretty simple, right? Wrong!
The loadClass() method required the custom ClassLoader to implement a laundry list of functions. In the Java 1.1 custom loadClass() they include the following:
Check to see whether or not the class has already been loaded
Check to see whether or not the class has been loaded by the system loader
Load the class from the respository
Define the class
Resolve the class
Return the new class to the caller
As you can see, this is quite a list, given that you are just trying to customize the way classes are input into the virtual machine (VM). Essentially, the java.lang.ClassLoader design forced you to do all the work for loading a class, rather than only the work required to bring a class into the VM in a new way.
Java 1.2 class-loading changes
For Java 1.2, a delegation design was put in place for java.lang.ClassLoader . In the delegation design, a custom ClassLoader delegates class loading to its parent. A ClassLoader parent can be either the bootstrap ClassLoader or another custom ClassLoader . In the event the parent ClassLoader can't load a class, a new method, named findClass() , is called on the ClassLoader subclass. In this manner, the custom ClassLoader is responsible for loading only the classes not available to the parent -- presumably classes that come from a new type of class repository.
Getting down to the nuts and bolts of the code, the loadClass() method is no longer abstract, relieving custom ClassLoader s from having to override it. In fact, new custom ClassLoader s should not override loadClass() ; instead they should override the new findClass() method to contain the custom class-loading logic. The java.lang.ClassLoader implementation of findClass() throws a ClassNotFoundException , essentially a no-op awaiting implementation by a custom ClassLoader .
Create a Java 1.2-delegation-style ClassLoader
Now I'll explain how to write a simple 1.2-style custom ClassLoader . First, you will subclass java.lang.ClassLoader , overriding findClass() as described earlier. The ClassLoader source file is available in Resources . I should note that the updates to java.lang.ClassLoader for Java 1.2 are backward compatible, so Java 1.1-style custom ClassLoader s will continue to work on a Java 1.2 virtual machine as they did on Java 1.1. Since the Java 1.2 version of java.lang.ClassLoader implements the delegation design in the loadClass() method, Java 1.1 custom ClassLoader s override the delegation code because they provide their own loadClass() implementation. Remember that in Java 1.1, java.lang.ClassLoader 's loadClass() method was abstract, requiring subclasses to provide an implementation.
This simple ClassLoader will load Java classes directly from the file system into subdirectories under a fixed directory named store, corresponding to their package specification. The ClassLoader will use Chuck McManis's technique (see Resources ) of ensuring that the system ClassLoader will not find the classes you want to load by renaming the class files with the extension .impl Any additional files used with the classes will be loaded from the store directory.
Here is an excerpt from the findClass() method in the SimpleClassLoader :
FileInputStream fi = null;
try
{
System.out.println("Simple1_2ClassLoader finding class: " + name);
String path = name.replace('.', '/');
fi = new FileInputStream("store/" + path + ".impl");
byte[] classBytes = new byte[fi.available()];
fi.read(classBytes);
definePackage(name);
return defineClass(name, classBytes, 0, classBytes.length);
}
The findClass() method is only responsible for loading the class bytes and returning a defined class. The method defineClass will convert the raw class bytes into a Java class suitable for JVM use. The parent ClassLoader , either another custom ClassLoader or the bootstrap ClassLoader , has already made several attempts at loading the class. It first attempts to find the class among the set of classes that have been previously loaded. If the class has not been previously loaded, it will call loadClass() on the parent ClassLoader (if there is one) or call it on the bootstrap ClassLoader . Only when those attempts have failed will your custom ClassLoader be called to load the class via findClass() . Since a lot of the work is done for you, the 1.2-custom ClassLoader is much simpler than its Java 1.1.x counterpart.
Chaining ClassLoaders together
Using the delegation model, you can chain together custom ClassLoader s. Chaining ClassLoader s lets you bring together multiple unique class-loading mechanisms. A new constructor for java.lang.ClassLoader that lets you assign a parent ClassLoader has been added to Java 1.2. Class-loading requests are delegated to the parent ClassLoader , and child ClassLoader s receive requests that the parent is unable to fulfill. If the no-argument ClassLoader constructor is used, the system ClassLoader is automatically assigned as the parent ClassLoader for delegation.
The following code sample shows the constructor you must implement to enable ClassLoader chaining. For completeness, custom ClassLoader s should provide this constructor to allow parent ClassLoader assignment.
Simple1_2ClassLoader(ClassLoader parent)
{
super(parent);
init();
}
Class-loading requests will be delegated to the parent ClassLoader , which will have the first shot at loading a class. This feature lets you create a chain of ClassLoader s that work together without having to use inheritance. Using an inheritance design would result in code with more interdependencies between the classes. Inheritance would make each subclass exposed to errors introduced by changing the superclass. Note that a findClass() method in a custom ClassLoader does not need to call its superclass's implementation of findClass() . However, it should throw a ClassNotFoundException whenever it is not able to load the class. When this exception is thrown, another custom ClassLoader in the chain has the chance to load it. In the event the class is never loaded, the ClassNotFoundException will of course be thrown to the application code.
Other Java 1.2 enhancements to java.lang.ClassLoader
For Java 1.2, runtime package versioning is available. That is, at runtime you can query the specification and implementation version information for a class. This capability is implemented via modifications to several classes in the Java runtime. The ClassLoader is central to the modifications that support runtime versioning.
The abstract class java.lang.ClassLoader contains the method definePackage() to define a package. Once a package is defined, you can use the new Java 1.2 java.lang.Package class to identify classes loaded from that package. However, the ClassLoader subclass actually defines a package. This means that java.lang.ClassLoader subclasses, such as java.net.URLClassLoader , actually contain the logic to determine the package-versioning information and call the definePackage method on the java.lang.ClassLoader superclass.
Thus, a custom ClassLoader may need to have the same logic to identify package information and make the appropriate call to java.lang.ClassLoader to define the package at runtime. The package information needs to be written in a manifest, so your custom ClassLoader must read the manifest and define the packages if the runtime-package-versioning system is to work. Of course, for some custom ClassLoader s, it may be determined that package versioning is not needed, but that should be a conscious choice, not an oversight.
I will illustrate the use of package versioning by enabling the simple ClassLoader to read a manifest from the store directory. Normally, the manifest would be contained in a jar or zip file; this is just an example:
// Check for a manifest in the store directory
try
{
fi = new FileInputStream("store\\MANIFEST.MF");
manifest = new Manifest(fi);
}
Resource loading
In addition to loading classes, ClassLoader s also locate resources in the repositories they are managing. These resources may be image files, audio files, or other types of data. For completeness, custom ClassLoader s should also provide this capability.
A ClassLoader locates resources using the delegation model in the same manner it did to load classes. A new method, fi
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: Create a custom Java 1.2-style ClassLoader - JavaWorld March 2000
View Tutorial: Create a custom Java 1.2-style ClassLoader - JavaWorld March 2000
Related
Tutorials:
Automatic Software Distribution of Java Applications
Automatic Software Distribution of Java Applications |
JSP best practices
Follow these tips for reusable and easily maintainable JavaServer Pages |
Java security evolution
and concepts, Part 2
Java security evolution
and concepts, Part 2 |
Jtrix: Web
services beyond SOAP
Jtrix: Web
services beyond SOAP |
Create your own type 3 JDBC driver, Part 2
Create your own type 3 JDBC driver, Part 2 |
Cracking Java byte-code encryption
Cracking Java byte-code encryption |
Back to your Class
roots
Back to your Class
roots |
Smartly load your
properties
Smartly load your
properties |
classworlds
classworlds
classworlds is a framework for container developers who require complex manipulation of Java\'s ClassLoaders. Java\'s native ClassLoader mechanims and classes can cause much headache and confusion for certain types of application developers. |
Good article
Good article |
Good
ideas
Good
ideas |
SQL Database Access with DBTags
SQL Database Access with DBTags
In a J2SE or J2EE application, Java Database Connectivity (JDBC) can be used to create a connection with a SQL database, create database tables, retrieve result sets, and update the database. To use a database from a Jav |
Software Download Central
compatible.
GNU getopt - Java port
A while back I found myself in need of a Java command line option parser. Unsatisfied with free versions I was able to find on the net, I volunteered to port the GNU getopt family of functions from C to Java. The current release |
Create Intelligent E-mail Filters with JavaMail and Classifier4j
Create Intelligent E-mail Filters with JavaMail and Classifier4j
Tired of the limitations and annoying false positives with commercial spam filters? Classifier4J is an open source Java library that will let you build custom applications that read e-mails |
Java Resources
There are all Java freebies. Some of these are old, and not under maintenance. Download and use them at your risk. In case of queries, mail subrahmanyam_avb@technologist.com or varalakshmi_a@techie.com. |
J2EE pathfinder: Implement JSP custom tags in five easy steps
JSP custom tags provide a standardized mechanism for separating presentation and business logic in a dynamic Web page, allowing page designers to focus on presentation while application developers code the back end. In this installment of J2EE pathfinder, |
Writing a Custom Counter Component
MIDP 2.0 introduced the javax.microedition.lcdui.CustomItem class. As the name implies, a developer can now create custom UI components by extending the CustomItem class. This tech tip designs and implements a UI component for displaying a numeric counter |
Struts, JavaServer Faces, and Java Studio Creator:
The Evolution of Web Application Frameworks Sun Microsystems' Craig McClanahan, the creator of the Apache Struts Framework, co-specification lead for JavaServer Faces 1.0, and prime architect for Sun Java Studio Creator's new release, explains all three. |
Advanced Synth
Take an in-depth look at the Synth look and feel, the newest addition to Swing introduced in Java 5.0. Synth lets developers rapidly create and deploy custom looks for an application by introducing the concept of a "skin" to Java UI programming. |
one-jar
One-JAR is a simple solution to a vexing problem in Java: how to distribute an application as a single jar-file, when it depends on multiple other jar-files. One-JAR uses a custom classloader to discover library jar files inside the main jar. |
|
|
|