Get the most out of Java's class loaders
Takeaway: Class loaders are one of Java's most powerful features. Find out why you should use customized class loaders, how to create your own class loaders, and what benefits there are to having a good working knowledge of the class loading mechanism.
Class loaders are one of Java's most powerful features. However, developers often forget about the class-loading component even though it's essential when you develop anything more complex than a "Hello, world" application. Class loader is the class responsible for finding and loading class files at runtime. Java allows you to use different class loaders, as well as your own customized class loader.
A Java program consists of many class files, each of which corresponds to a single Java class. These class files are not loaded into memory all at once like in a static-built C program—they are loaded on demand. This is where the class loader comes into play; it gets platform independent compiled byte code from a source (usually either a .class or .jar file) and loads into JVM memory space so they can be interpreted and executed. By default, each class in an application is loaded by some instance of a java.lang.ClassLoader. You are free to enhance its functionality since it can be easily inherited.
Why you should use customized class loaders
The default java.lang.ClassLoader is only able to load classes from the local filesystem. Java is designed to be flexible enough to get classes from places other than the local hard drive or network, and do special things before actually loading. For example, your application can routinely check a newer version of a plug-in class on a Web site or FTP and automatically verify a digital signature to make sure that only trusted code will be executed. Many well-known application servers use their own sophisticated class loaders.
The so-called bootstrap class loader is usually used by default; it is responsible for loading key classes like java.lang.Object and other runtime code located in the rt.jar file into memory. Since the Java Language Specification does not provide any details about the bootstrap class loader (because it has a native implementation), different JVMs may have different behavior of its default class loader. If you have ever seen applets executing on some Web page, you have already used a custom class loader. The applet viewer built in the browser contains a class loader that accesses a Web site on a remote server, loads the raw byte-code files via HTTP, and turns them into classes inside the JVM.
Create your own class loader
Class loaders (except the bootstrap class loader) have a parent class loader, which is basically the class loader instance that loaded the class loader. The most important thing is to correctly set the parent class loader. After that, you can use the getParent() method of the class loader in order to delegate class requests to it (e.g., when your custom class loader cannot find a class using your specialized method). You have to set the parent class loader in the constructor as a parameter for the java.lang.ClassLoader constructor:
public class MyClassLoader extends ClassLoader{
public MyClassLoader(){
super(MyClassLoader.class.getClassLoader());
}
}
The method loadClass(String name) is the entry point to our ClassLoader. The name parameter is a fully qualified class name (FQCN), i.e., a class name with package. If the parent class loader is set correctly, when MyClassLoader is requested to load a class by loadClass(String name) and it is unable to find the class, it should ask the parent first. If the parent also cannot find the class, the findClass(String name) method is invoked. The default implementation of findClass(String name) normally throws ClassNotFoundException, an exception which most developers know all too well. Developers of custom class loaders are expected to override this method when they inherit the java.lang.ClassLoader.
The purpose of the findClass() method is to contain all specialized code for MyClassLoader—without duplicating the other code such as calling the system ClassLoader when our loader has failed. In this method, the ClassLoader needs to fetch the byte code from an arbitrary source. Once the byte code is retrieved, the method should call the defineClass() method. It is extremely important which instance of ClassLoader called the method for the loaded class. Thus, if two ClassLoader instances define byte code from the same or different sources, the defined classes are treated as different.
Let's take two similar class loaders MyClassLoader1 and MyClassLoader2, which are capable of finding the byte code of MyCoolClass from the same source. If an application will load two instances of MyCoolClass independently by way of two class loaders (we'll say coolClass1 via MyClassLoader1 and coolClass2 via MyClassLoader2), MyCoolClass.class will be defined for them independently as well. When you execute the following code:
MyCoolClass coolClass1 = (MyCoolClass)coolClass2;
you will get the ClassCastException. (Developers often get this exception if they don't have a good understanding of the class loading mechanism.) Since they are defined by different loaders, the JVM sees two distinct class types. The variables coolClass1 and coolClass2 are not type compatible, although it is of the same class type and loaded from the same source.
Whether you override findClass() or loadClass(), the method getSystemClassLoader() gives you direct access to the system ClassLoader in the form of an actual ClassLoader object. You can also access it implicitly through the findSystemClass(String name) call. The method getParent() allows you to get the parent class loader. Listing A contains an example of a ready-to-run custom class loader.
Summary
If you have a good understanding of the class loading mechanism, it can protect you in the long run from debugging ClassNotFound or ClassCastException errors in the application. This is especially important when an application works inside a third-party application server since such app servers often use proprietary and sophisticated class loaders.
Peter V. Mikhalenko is a Sun certified professional who works for Deutsche Bank as business consultant.
Print/View all Posts Comments on this article
|
|
|
|
|
|
White Papers, Webcasts, and Downloads
- Five Steps to Determine When to Virtualize YourServers VMware Thinking of virtualizing the servers at your company? Use this step-by-step guide to determine when's the best time to make your big move. Download Now
- Why Isn't Server Virtualization Saving Us More? A Few Small Changes May Dramatically Increase Your Efficiency VMware Ever wonder why your company isn't saving more from its server virtualization? Making a few small changes could dramatically increase your efficiency. Download Now
- Building the Virtualized Enterprise with VMware Iinfrastructure VMware VMware virtualization software has been adopted by over 120,000 enterprise ... Download Now
- Building the Virtualized Enterprise with VMware Infrastructure VMware This paper explains how adopting a virtual infrastructure -- comprised of server, storage, and networking virtualization technologies -- can help your organization build a sustainable competitive ... Download Now
- The True Costs of Virtual Server Solutions VMware Discover ways to streamline and simplify your assessment of the total acquisition costs of a server virtualization environment. Download Now
Article Categories
- Security
- Security Solutions, IT Locksmith
- Networking and Communications
- E-mail Administration NetNote, Cisco Routers and Switches
- CIO and IT Management
- Project Management, CIO Issues, Strategies that Scale
- Desktops, Laptops & OS
- Windows 2000 Professional, Microsoft Word, Microsoft Excel, Microsoft Access, Windows XP,
- Data Management
- Oracle, SQL Server
- Servers
- Windows NT, Linux NetNote, Windows Server 2003
- Career Development
- Geek Trivia
- Software/Web Development
- Web Development Zone, Visual Basic, .NET

