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> | </a></li> | ||||
| <li><a href="#javadoc-cannot-execute"> | <li><a href="#javadoc-cannot-execute"> | ||||
| JavaDoc failed: java.io.IOException: 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> | </a></li> | ||||
| </ul> | </ul> | ||||
| </blockquote> | </blockquote> | ||||
| @@ -1873,6 +1877,113 @@ mv /tmp/foo $ANT_HOME/bin/antRun | |||||
| </blockquote> | </blockquote> | ||||
| </td></tr> | </td></tr> | ||||
| </table> | </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> | </a> | ||||
| </blockquote> | </blockquote> | ||||
| </td></tr> | </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 | Do neither of the above, and instead, specify their locations using | ||||
| a <code><classpath></code> element in the build file. | 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> | </ol> | ||||
| </p> | </p> | ||||
| @@ -951,6 +951,122 @@ mv /tmp/foo $ANT_HOME/bin/antRun | |||||
| the front of the PATH fixes the problem.</p> | the front of the PATH fixes the problem.</p> | ||||
| </answer> | </answer> | ||||
| </faq> | </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> | </faqsection> | ||||
| </document> | </document> | ||||