PR: 6606 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272510 13f79535-47bb-0310-9956-ffa450edef68master
@@ -288,6 +288,10 @@ | |||
</a></li> | |||
<li><a href="#javadoc-cannot-execute"> | |||
JavaDoc failed: java.io.IOException: javadoc: cannot execute | |||
</a></li> | |||
<li><a href="#delegating-classloader"> | |||
<style> or <junit> ignores my | |||
<classpath> | |||
</a></li> | |||
</ul> | |||
</blockquote> | |||
@@ -1873,6 +1877,113 @@ mv /tmp/foo $ANT_HOME/bin/antRun | |||
</blockquote> | |||
</td></tr> | |||
</table> | |||
</a> | |||
<a name="delegating-classloader"> | |||
<table border="0" cellspacing="0" cellpadding="2" width="100%"> | |||
<tr><td bgcolor="#828DA6"> | |||
<font color="#ffffff" face="arial,helvetica,sanserif"> | |||
<strong> | |||
<style> or <junit> ignores my | |||
<classpath> | |||
</strong> | |||
</font> | |||
</td></tr> | |||
<tr><td> | |||
<blockquote> | |||
<p>These tasks don't ignore your classpath setting, you | |||
are facing a common problem with delegating classloaders.</p> | |||
<p>First of all let's state that Ant adds all | |||
<code>.jar</code> files from <code>ANT_HOME/lib</code> to | |||
<code>CLASSPATH</code>, therefore "in | |||
<code>CLASSPATH</code>" shall mean "either in your | |||
<code>CLASSPATH</code> environment variable or | |||
<code>ANT_HOME/lib</code>" for the rest of this | |||
answer.</p> | |||
<p>This question 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 | |||
<code>CLASSPATH</code>.</p> | |||
<p>The root of the problem is that the class that needs the | |||
external library is on the <code>CLASSPATH</code>.</p> | |||
<p>When you specify a nested <code><classpath></code> 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.</p> | |||
<p>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.</p> | |||
<p>In the case of <code><junit></code> it is the task | |||
implementation itself and in the case of | |||
<code><style></code> it is the implementation of the | |||
<code>org.apache.tools.ant.taskdefs.XSLTLiaison</code> | |||
class.</p> | |||
<p>Ant's class loader implementation uses Java's | |||
delegation model, see <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html</a> | |||
the paragraph</p> | |||
<blockquote>The <code>ClassLoader</code> class uses a | |||
delegation model to search for classes and resources. Each | |||
instance of <code>ClassLoader</code> has an associated parent | |||
class loader. When called upon to find a class or resource, a | |||
<code>ClassLoader</code> 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 <code>ClassLoader</code> | |||
instance.</blockquote> | |||
<p>This means, Ant's class loader will consult the | |||
bootstrap class loader first, which tries to load classes from | |||
<code>CLASSPATH</code>. The bootstrap class loader | |||
doesn't know anything about Ant's class loader or | |||
even the path you have specified.</p> | |||
<p>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 <code>CLASSPATH</code> as well - it doesn't | |||
know anything else - and will not find it unless the library | |||
is in <code>CLASSPATH</code> as well.</p> | |||
<p>To solve this, you have two major options:</p> | |||
<ol> | |||
<li>put all external libaries you need in | |||
<code>CLASSPATH</code> as well this is not what you want, | |||
otherwise you wouldn't have found this FAQ entry.</li> | |||
<li>remove the class that loads the external library from | |||
the <code>CLASSPATH</code>.</li> | |||
</ol> | |||
<p>The easiest way to do this is to remove | |||
<code>optional.jar</code> from <code>ANT_HOME/lib</code>. If | |||
you do so, you will have to <code><taskdef></code> all | |||
optional tasks and use nested <code><classpath></code> | |||
elements in the <code><taskdef></code> tasks that point | |||
to the new location of <code>optional.jar</code>. Also, | |||
don't forget to add the new location of | |||
<code>optional.jar</code> to the | |||
<code><classpath></code> of your | |||
<code><style></code> or <code><junit></code> | |||
task.</p> | |||
<p>If you want to avoid to <code><taskdef></code> 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 <code>optional.jar</code> and put them into a | |||
separate archive. Add this separate archive to the | |||
<code><classpath></code> of your | |||
<code><style></code> or <code><junit></code> task | |||
- and make sure the separate archive is not in | |||
<code>CLASSPATH</code>.</p> | |||
<p>In the case of <code><junit></code> you'd have | |||
to remove all classes that are in the | |||
<code>org/apache/tools/ant/taskdefs/optional/junit</code> | |||
directory, in the <code><style></code> case it is one of | |||
the <code>*Liaison</code> classes in | |||
<code>org/apache/tools/ant/taskdefs/optional</code>.</p> | |||
<p>If you use the option to break up <code>optional.jar</code> | |||
for <code><junit></code>, you still have to use a | |||
<code><taskdef></code> with a nested | |||
<code><classpath></code> to define the junit task.</p> | |||
</blockquote> | |||
</td></tr> | |||
</table> | |||
</a> | |||
</blockquote> | |||
</td></tr> | |||
@@ -34,8 +34,8 @@ include their locations in your <code>CLASSPATH</code> environment variable. | |||
Do neither of the above, and instead, specify their locations using | |||
a <code><classpath></code> element in the build file. | |||
See <a href="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6606">the | |||
bugs database</a> for details. | |||
See <a href="../../faq.html#delegating-classloader" target="_top">the | |||
FAQ</a> for details. | |||
</ol> | |||
</p> | |||
@@ -951,6 +951,122 @@ mv /tmp/foo $ANT_HOME/bin/antRun | |||
the front of the PATH fixes the problem.</p> | |||
</answer> | |||
</faq> | |||
<faq id="delegating-classloader"> | |||
<question><style> or <junit> ignores my | |||
<classpath></question> | |||
<answer> | |||
<p>These tasks don't ignore your classpath setting, you | |||
are facing a common problem with delegating classloaders.</p> | |||
<p>First of all let's state that Ant adds all | |||
<code>.jar</code> files from <code>ANT_HOME/lib</code> to | |||
<code>CLASSPATH</code>, therefore "in | |||
<code>CLASSPATH</code>" shall mean "either in your | |||
<code>CLASSPATH</code> environment variable or | |||
<code>ANT_HOME/lib</code>" for the rest of this | |||
answer.</p> | |||
<p>This question 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 | |||
<code>CLASSPATH</code>.</p> | |||
<p>The root of the problem is that the class that needs the | |||
external library is on the <code>CLASSPATH</code>.</p> | |||
<p>When you specify a nested <code><classpath></code> 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.</p> | |||
<p>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.</p> | |||
<p>In the case of <code><junit></code> it is the task | |||
implementation itself and in the case of | |||
<code><style></code> it is the implementation of the | |||
<code>org.apache.tools.ant.taskdefs.XSLTLiaison</code> | |||
class.</p> | |||
<p>Ant's class loader implementation uses Java's | |||
delegation model, see <a | |||
href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html</a> | |||
the paragraph</p> | |||
<blockquote>The <code>ClassLoader</code> class uses a | |||
delegation model to search for classes and resources. Each | |||
instance of <code>ClassLoader</code> has an associated parent | |||
class loader. When called upon to find a class or resource, a | |||
<code>ClassLoader</code> 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 <code>ClassLoader</code> | |||
instance.</blockquote> | |||
<p>This means, Ant's class loader will consult the | |||
bootstrap class loader first, which tries to load classes from | |||
<code>CLASSPATH</code>. The bootstrap class loader | |||
doesn't know anything about Ant's class loader or | |||
even the path you have specified.</p> | |||
<p>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 <code>CLASSPATH</code> as well - it doesn't | |||
know anything else - and will not find it unless the library | |||
is in <code>CLASSPATH</code> as well.</p> | |||
<p>To solve this, you have two major options:</p> | |||
<ol> | |||
<li>put all external libaries you need in | |||
<code>CLASSPATH</code> as well this is not what you want, | |||
otherwise you wouldn't have found this FAQ entry.</li> | |||
<li>remove the class that loads the external library from | |||
the <code>CLASSPATH</code>.</li> | |||
</ol> | |||
<p>The easiest way to do this is to remove | |||
<code>optional.jar</code> from <code>ANT_HOME/lib</code>. If | |||
you do so, you will have to <code><taskdef></code> all | |||
optional tasks and use nested <code><classpath></code> | |||
elements in the <code><taskdef></code> tasks that point | |||
to the new location of <code>optional.jar</code>. Also, | |||
don't forget to add the new location of | |||
<code>optional.jar</code> to the | |||
<code><classpath></code> of your | |||
<code><style></code> or <code><junit></code> | |||
task.</p> | |||
<p>If you want to avoid to <code><taskdef></code> 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 <code>optional.jar</code> and put them into a | |||
separate archive. Add this separate archive to the | |||
<code><classpath></code> of your | |||
<code><style></code> or <code><junit></code> task | |||
- and make sure the separate archive is not in | |||
<code>CLASSPATH</code>.</p> | |||
<p>In the case of <code><junit></code> you'd have | |||
to remove all classes that are in the | |||
<code>org/apache/tools/ant/taskdefs/optional/junit</code> | |||
directory, in the <code><style></code> case it is one of | |||
the <code>*Liaison</code> classes in | |||
<code>org/apache/tools/ant/taskdefs/optional</code>.</p> | |||
<p>If you use the option to break up <code>optional.jar</code> | |||
for <code><junit></code>, you still have to use a | |||
<code><taskdef></code> with a nested | |||
<code><classpath></code> to define the junit task.</p> | |||
</answer> | |||
</faq> | |||
</faqsection> | |||
</document> |