ClassLoadingOverview

Overview of ClassLoading Issues

 

Why another page on classloading? Because sometimes when something is explained in a different way with different emphasis it is exactly what somebody needs for their problem.

 

THIS PAGE IS INTENDED TO BE A CHECKLIST OF COMMON PROBLEMS WITH SOLUTIONS REFERENCED ELSEWHERE

 

PROBLEMS

 

I get ClassNotFoundException

 

This means that some dynamic classloading, i.e. classloader.loadClass() cannot find the class. This FAQ deals with the problem.

 

I get NoClassDefFoundError

 

This means that some JVM initiated classloading failed. Usually because of an import on an another class that was in the process of being loaded. Again this FAQ deals with the problem.

 

 

I get ClassCastException

 

There are some places where it reports this when it really means ClassNotFoundException, e.g. the CORBA

PortableRemoteObject.narrow()

 

Assuming it is the same class name, this problem relates to classes getting loaded from different

classloaders. At compile time your class has only one identity, its name. If you "deploy" a class many times in different jars, it has multiple identities. They are not the same. See below for more information on the solutions to this problem.

 

This can also be caused by you only redeploying part of your application. e.g. a webapp uses an EJB

and you only redeploy the EJB. The webapp will still have the old versions of the classes.

 

I get LinkageError

 

Assuming you are running the version of the class you compiled over, this is a subtle form of ClassCastException when classes are passed between classloaders without doing a cast. e.g. you have a class in two separate deployments and you invoke a method that passes an object from one to the other but using an interface that the class implements. (See chapter 2 of the admin docs for more information of this subtle problem).

 

I get ClassCircularityError

 

Assuming this isn't a real circular reference, this is caused by a JDK bug. The solution is to avoid concurrent classloading for this class and probably related classes

 

 

 

ISSUES AND DEFINITIONS

 

What are the types of things you want to do with classloading?

 

Sharing and isolation

 

Sharing

 

The most common thing to do is to share classes. i.e. choose one version of the classes, test it and let everybody use it. This is usually the easiest to manage, understand and it is certainly the most efficient in terms of resources. It also directly mirrors your build environment.

 

Isolate

 

You don't want to share your classes with others but you do want to share common classes and use application server provided classes.

 

JavaSE Spec compliance

 

Related to sharing and isolation. Do you want to use application server classes where provided?

 

Non Spec compliance (except the servlet spec

 

You don't want to use application server classes or any shared classes. You want your own version.

 

Caller semantics

 

Call by reference

 

This is probably what you are familiar with one java class invokes a method on another.

 

Call by value

 

This simulates a remote invocation over the network. Parameters are "marshalled" - turned into a byte stream - then "unmarshalled" with destinations classloader. Any return value or exception is again "marshalled" then "unmarshalled" with the origin's classloader.

 

NOTE: You cannot use call-by-value for EJB local invocations. It simulates a remote call.

 

 

 

PROBLEMS WITH THESE ISSUES

 

Isolation

 

If you choose not to share you will have problems talking to other applications that don't have the same version of the class. The solution is to use call-by-value to "translate" the classes between the classloaders.

 

Spec compliance

 

If you choose not to use the application server classes, you will have problems talking to the application server itself.

 

Call by value

 

The extra work of object to bytestream translation is a cpu overhead. Typically you will need 10 times the cpu power (or 10 times the number of machines to run compared to an application that uses call-by-reference.

 

Servlet configuration

 

The servlet spec says that you shouldn't use JavaSE spec compliance. This essentially means it will use anything you put in

WEB-INF/classes

or

WEB-INF/lib

. Since these are usually "dumping grounds" for all sorts of "rubbish", this is usually a bad idea.

 

This isn't quite true since there is a configurable filter to ignore certain packages.

 

If you do want isolation, then configure that and share the application server classes.

 

Redeployment

 

If you share classes with another application, make sure you either don't redeploy the shared classes or you redeploy everybody when they change.

 

 

 

COMMON CONFIGURATIONS

 

Share everything

 

This is the default as long as you turn off the servlet spec classloader.

 

EAR Deployer - ease of use

 

Setting

isolated=true

and

call-by-value=true

on the

ear.deployer

and

enabling call-by-value for jndi will give you isolation and class translation for any applications deployed as ears.

 

Listing an deployment's contents

If you are relying on a jars ClassPath manifest header to pickup classes, its useful to display an overview of the archive contents including the ClassPath references. The attached ListJar ListJar.java, ListJar.class can be used for this. Run the ListJar program passing in the archive to list. For example:

[starksm@banshee9100 main]$ java -cp . ListJar cpmanifest.ear
/cvs/JBoss4.0/jboss-4.0/testsuite/output/lib/cpmanifest.ear
+- META-INF/MANIFEST.MF
+- abstract.jar (archive)
|  +- META-INF/MANIFEST.MF
|  +- org/jboss/test/jmx/loading/AbstractBean.class
+- concrete.jar (archive)
|  +- META-INF/MANIFEST.MF Class-Path: ./abstract.jar
|  +- org/jboss/test/jmx/loading/Concrete.class
|  +- org/jboss/test/jmx/loading/ConcreteBean.class
|  +- org/jboss/test/jmx/loading/ConcreteHome.class
|  +- META-INF/ejb-jar.xml
+- META-INF/application.xml
Done

This shows that the cpmanifest.ear/concrete.jar includes the abstract.jar via its Class-Path.

 

Other

 

The mechanisms for each deployment type are explained in the main classloading configuration link

 

More complicated

 

Sometimes you want isolation, but you still want to share amongst a select number of applications. To do this, assign them to same classloader repository with a specific name of your choosing, rather than using the automatic one created by

isolated=true

on the EARDeployer. This way you have your own little world to "play in".

 

Related