diff --git a/docs/faq.html b/docs/faq.html index 87a7b0fa0..24b3f0e99 100644 --- a/docs/faq.html +++ b/docs/faq.html @@ -288,6 +288,10 @@
  • JavaDoc failed: java.io.IOException: javadoc: cannot execute +
  • +
  • + <style> or <junit> ignores my + <classpath>
  • @@ -1873,6 +1877,113 @@ mv /tmp/foo $ANT_HOME/bin/antRun + + + + + +
    + + + <style> or <junit> ignores my + <classpath> + + +
    +
    +

    These tasks don't ignore your classpath setting, you + are facing a common problem with delegating classloaders.

    +

    First of all let's state that Ant adds all + .jar files from ANT_HOME/lib to + CLASSPATH, therefore "in + CLASSPATH" shall mean "either in your + CLASSPATH environment variable or + ANT_HOME/lib" for the rest of this + answer.

    +

    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 + 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 FAQ entry.
    2. + +
    3. remove the class that loads the external library from + the CLASSPATH.
    4. +
    +

    The easiest way to do this is to remove + optional.jar from ANT_HOME/lib. 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.

    +
    +
    diff --git a/docs/manual/OptionalTasks/junit.html b/docs/manual/OptionalTasks/junit.html index 4b4775c08..d37a724aa 100644 --- a/docs/manual/OptionalTasks/junit.html +++ b/docs/manual/OptionalTasks/junit.html @@ -34,8 +34,8 @@ include their locations in your CLASSPATH environment variable. Do neither of the above, and instead, specify their locations using a <classpath> element in the build file. -See the -bugs database for details. +See the +FAQ for details.

    diff --git a/xdocs/faq.xml b/xdocs/faq.xml index 6d3d177e7..c891770a8 100644 --- a/xdocs/faq.xml +++ b/xdocs/faq.xml @@ -951,6 +951,122 @@ mv /tmp/foo $ANT_HOME/bin/antRun the front of the PATH fixes the problem.

    + + + <style> or <junit> ignores my + <classpath> + + +

    These tasks don't ignore your classpath setting, you + are facing a common problem with delegating classloaders.

    + +

    First of all let's state that Ant adds all + .jar files from ANT_HOME/lib to + CLASSPATH, therefore "in + CLASSPATH" shall mean "either in your + CLASSPATH environment variable or + ANT_HOME/lib" for the rest of this + answer.

    + +

    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 + 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 FAQ entry.
    2. + +
    3. remove the class that loads the external library from + the CLASSPATH.
    4. +
    + +

    The easiest way to do this is to remove + optional.jar from ANT_HOME/lib. 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.

    +
    +