You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Conor MacNeill <co...@cortexebusiness.com.au> on 2000/08/09 17:27:21 UTC

Classloader improvements for EJBC

Hi,

This is a long (and pretty technical) message.

I am attaching updated versions of the AntClassLoader and the EJBC classes
rather than committing the changes since this change may be a little
controversial in it use of Java's classloading facilities. Before I get into
that let me give the benefits of this change. This change allows the ejbc
helper class and weblogic's ejbc compiler to be run within the ant VM. The
helper class now has access to the ant Project object and uses that to
determine if Jikes is bieng used for the compiler. If so it is also used for
ejbc operations.

The problem is with the work the code has to do to ensure the right classes
end up in the right class loader. It is a little messy. There is a tricky
problem with classloaders when the classpaths of the classloader and the
system class loader overlap. That is a class file exists in both the system
class path and the classpath defined for the class loader. This overlap can
have undesirable side effects as follows:

1. A class, loaded through different loaders is not considered to be the
same class. This means that an instance cannot be assigned to a reference
even if it is the same underlying class. Attempts to do so will generate a
ClassCastException. This issue is pretty well known.

2. Any classes which are subsequently loaded by a class use the same class
loader as was actually used to load the class. For those of you familiar
with the terms, a class uses its defining class loader and not its
initiating class loader. If the next class to be loaded only exists in the
classpath of the other class loader, the class will not be found, even if
that other class loader is the initiating class loader.

Classes to be loaded fall into three categories. Those which only exist in
the system classpath, those which only exist in the loader's classpath and
those which exist in both classpaths. In the first two cases the loader to
use is obvious. The tricky issue is to handle the loading of classes which
exist on the classpath of both loaders.

The behaviour described in the classloader documentation is to always try
and load from the system classpath first. This approach guarantees that
classes loaded will always be compatible with references in the system
classpath. The drawback comes when those loaded classes attempt to load
other classes which are in the loader's classpath but not in the system
classpath. These subsequent classes will not be found.

In the situation of the ejbc task, I wanted to communicate from the ejbc
task to the helper task through an interface (rather than reflection). The
ejbc task and the interface are thus loaded on the system class loader.
Since I want the helper to access classes not on the classpath, I want it
loaded into the customer class loader, even though it exists on the system
classpath. The helper class loads weblogic.ejbc, which may or may not exist
on the classpath, depending on each user's setup. Finally weblogic.ejbc
deserialises a deployment descriptor which will depend on classes which will
most likely not exist on the system classpath, since they are part of the
project being built by ant.

So, we have the interface and ant classes loaded on the system loader. The
helper class and weblogic.ejbc must be loaded on the custom class loader
even though they may be available in the system class path. I have added
facilities to the AntClassLoader to allow you to control the class loading
to meet these needs. Firstly the behaviour of loading from the system
classpath first can be reversed. The loader can be configured to consult its
own classpath first and then the system loader. That change is not
sufficient since it would try to load ant classes onto the ant loader and
not the system loader. Therefore I also allow pareticular package roots to
be designated as system package roots. All classes, whose package begins
with that root will load from the system class first. Ejbc does the
following

        loader.addSystemPackageRoot("org.apache.tools.ant");
        loader.addSystemPackageRoot("javax");

Javax is required as a system package root because weblogic supplies its own
javax.swing and javax.accessibility classes. If these are loaded in place of
the standard system classes, Linkage errors can result (violation of loader
constraints). The javax packages which are not present in the system
classpath (javax.ejb) will be loaded in the ant loader.

If you got this far, I'd like your opinions on whether all this mucking
around with class loaders is worth the convenience it gives. Can the Jikes
support be provided over the current parameter based interface, even if it
is a bit klunky.

Conor