ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 6606] - META-BUG problems with delegating classloaders
Date Thu, 21 Feb 2002 11:19:26 GMT
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6606>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6606

META-BUG problems with delegating classloaders





------- Additional Comments From bodewig@apache.org  2002-02-21 11:19 -------
OK, first of all let's state that Ant adds all .jar files from ANT_HOME/lib
to CLASSPATH, therefore when I say "in CLASSPATH" in the rest, it means "either
in your CLASSPATH environment or ANT_HOME/lib".

This bug collects a common type of problem: A task needs an external library and
it has a nested classpath element so that you can point it to this external
library, but that doesn't work unless you put the external library into the
CLASSPATH.

The root of the problem is that the class that needs the external library
is on the CLASSPATH.

When you specify a nested <classpath> in Ant, Ant creates a new class loader
that uses the path you have specified.  It then tries to load additional
classes from this classloader.

In most cases - for example the two cases above - Ant doesn't load the external
library directly, it is the loaded class that does so.

In the case of <junit> it is the task implementation itself and in the case
of <style> it is the implementation of the
org.apache.tools.ant.taskdefs.XSLTLiaison class.

Ant's class loader implementation uses Java's delegation model, see
http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html
the paragraph

> The ClassLoader class uses a delegation model to search for classes and 
> resources. Each instance of ClassLoader has an associated parent class loader.
> When called upon to find a class or resource, a ClassLoader instance will 
> delegate the search for the class or resource to its parent class loader
> before attempting to find the class or resource itself. The virtual machine's
> built-in class loader, called the bootstrap class loader, does not itself have
> a parent but may serve as the parent of a ClassLoader instance.

This means, Ant's class loader will consult the bootstrap class loader first,
which tries to load classes from CLASSPATH.  The bootstrap class loader
doesn't know anything about Ant's class loader or even the path you have specified.

If the bootstrap class loader can load the class Ant has asked it to load,
this class will try to load the external library from CLASSPATH as well - it
doesn't know anything else - and will not find it unless the library is in
CLASSPATH as well.

To solve this, you have two major options:

(1) put all external libaries you need in CLASSPATH as well

this is not what you want, otherwise you wouldn't have found this bug report.

(2) remove the class that loads the external library from the CLASSPATH.

The easiest way to do this is to remove optional.jar from ANT_HOME.  If you do
so, you will have to <taskdef> all optional tasks and use nested <classpath>
elements in the <taskdef> tasks that point to the new location of optional.jar.
Also, don't forget to add the new location of optional.jar to the <classpath>
of your <style> or <junit> task.

If you want to avoid to <taskdef> all optional tasks you need, the only other
option is to remove the classes that should not be loaded via the bootstrap
class loader from optional.jar and put them into a separate archive. Add this
separate archive to the <classpath> of your <style> or <junit> task - and
make
sure the separate archive is not in CLASSPATH.

In the case of <junit> you'd have to remove all classes that are in the
org/apache/tools/ant/taskdefs/optional/junit directory, in the <style> case
it is one of the *Liaison classes in org/apache/tools/ant/taskdefs/optional.

If you use the option to break up optional.jar for <junit>, you still have to
use a <taskdef> with a nested <classpath> to define the junit task.

Does this description make any sense?  Would it help people who face the same
problem you have seen?  If not, how can we improve it?

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message