JBoss at Work. A Practical Guide
Authors: Davis S. Marrs T.
Published year: 2004
Pages: 156-157/197
Buy this book on amazon.com >>

A.4. Common ClassLoader Issues

ClassLoader issues are difficult to find and take a long time to debug. They fall into one of two categories:



Not enough visibility

You'll see one of the following exceptions:

  • ClassNotFoundException

Java API methods such as Class.forName( ) or ClassLoader.loadClass( ) throw a ClassNotFoundException . This exception happens when a class loader tries to load a class and can't find the class. Here are some possible causes:

  • A JAR or directory for the class is not available, so the ClassLoader asked to load the class, or to its parent(s).

  • The wrong ClassLoader is used to load the class.



NoClassDefFoundError

A NoClassDefFoundError has the same causes as the ClassNotFoundException , but there is an additional reasona class depends on other classes that are inaccessible from the current ClassLoader. The other classes may reside only in a child or sibling ClassLoader, neither of which is available to the current ClassLoader.



Too much visibility

This happens when you have a duplicate class and the problem manifests as a ClassCastException . For example, you could include the same JAR file (bundled with several libraries) more than once in your deployment.



A.5. ClassLoader Options

In the Java API, you can explicitly use either the System (or Application), Current, or the Thread Context ClassLoader.

You can access the System ClassLoader by calling ClassLoader.getSystemClassLoader( ) . In most J2EE application servers, the System ClassLoader is too high in the hierarchy and will not find the resources packaged in your application's EJB JAR or WAR. In JBoss, using the System ClassLoader is still a problem because the ClassLoader Repository holds references to all deployed applications, so you could easily have a naming conflict if more than one application uses the same class.

The Current ClassLoader is the ClassLoader that loaded the class that contains the method that's currently executing. Class.getResource( ) and the one-parameter version of Class.forName( ) use the Current ClassLoader by default. The Current ClassLoader is a better choice than the System ClassLoader, but there are still problems with using the Current ClassLoader:

  • You may not know who calls your class, and the current ClassLoader could be up too high in the ClassLoader to find the resources that your class needs.

  • In JBoss, you could have the same naming conflict with Class Loader Repository that you had with the System ClassLoader.

You gain access to the current Thread Context ClassLoader by calling Thread.currentThread( ).getContextClassLoader( ) . The Thread Context ClassLoader is the ClassLoader used by the creator of the Thread that runs your code. The Thread Context ClassLoader works in a way that's contrary to the Delegation Model by enabling a parent ClassLoader to access classes from any of its child ClassLoaders. Sometimes a parent ClassLoader needs to see classes that one of its child ClassLoaders instantiates at runtime. Use the Thread Context Class Loader for the following reasons:

  • In JBoss, you're guaranteed to load the class or property file from your application by using the Thread Context ClassLoader. Even though the JBoss ClassLoader Repository may have the same class or property from several applications, the Thread Context ClassLoader picks the class or property that belongs to your application.

  • The EJB specification forbids EJBs to use the Current Class Loader, and since the System Class Loader isn't a workable option, you're left with the Thread Context ClassLoader. See the Programming Restrictions section in the EJB specification for further details.

Here are a couple of practical uses of the Thread Context ClassLoader:

  • If you have a factory method that uses Class.forName( ) to instantiate classes dynamically, pass the Thread Context ClassLoader as a parameter to Class.forName( ) .

  • To load a Properties file in your application's CLASSPATH , call Thread.currentThread( ).getContextClassLoader( ).getResourceAsStream( ) to find the Properties file, and use the resulting InputStream when calling Properties.load( ) .


JBoss at Work. A Practical Guide
Authors: Davis S. Marrs T.
Published year: 2004
Pages: 156-157/197
Buy this book on amazon.com >>

Similar books on Amazon