When running Ant 1.4 on Windows XP and JDK 1.4, I get
@@ -1610,31 +1618,23 @@ mv /tmp/foo $ANT_HOME/bin/antRun
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.
- Technically the sentence above isn't true for Ant 1.6
- and later anymore, but the result is the same. For the sake
- of this discussion, CLASSPATH
and
- ANT_HOME/lib
are identical.
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
.
+ that doesn't work unless you put the external library
+ into the CLASSPATH
or place it in
+ ANT_HOME/lib
.
+ Some background is necessary before we can discuss
+ solutions for Ant
+ 1.5.x and Ant
+ 1.6.x.
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 most cases - for example using <style> or
+ <junit> - 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
@@ -1654,16 +1654,37 @@ mv /tmp/foo $ANT_HOME/bin/antRun
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
+
The possible solutions depend on the version of Ant you
+ use, see the next sections.
+
+
+ <style> or <junit> ignores my
+ <classpath> - Ant 1.5.x version
+
+ Please read the previous
+ entry before you go ahead.
+ First of all let's state that Ant's wrapper script
+ (ant
or ant.bat
) 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.
+ The root of the problem is that the class that needs the
+ external library is on the CLASSPATH
.
+ Let's see what happens when you load the <junit>
+ task. 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.
+ asked it to load (which it can if optional.jar
is
+ part of CLASSPATH
), 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:
- put all external libraries you need in
@@ -1673,8 +1694,6 @@ mv /tmp/foo $ANT_HOME/bin/antRun
- remove the class that loads the external library from
the
CLASSPATH
.
- Using The Second Option with Ant 1.5.4 and
- Earlier:
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
@@ -1701,22 +1720,98 @@ mv /tmp/foo $ANT_HOME/bin/antRun
directory, in the <style>
case it is one of
the *Liaison
classes in
org/apache/tools/ant/taskdefs/optional
.
- Using The Second Option with Ant 1.6 and
- later:
+ If you use the option to break up optional.jar
+ for <junit>
or remove
+ ant-junit.jar
, you still have to use a
+ <taskdef>
with a nested
+ <classpath>
to define the junit task.
+
+
+ <style> or <junit> ignores my
+ <classpath> - Ant 1.6.x version
+
+ Please read the general
+ entry before you go ahead.
+ The wrapper script of Ant 1.6.x no longer adds the contents
+ of ANT_HOME/lib
to CLASSPATH
,
+ instead Ant will create a classloader on top of the bootstrap
+ classloader - let's call it the coreloader for the rest of
+ this answer - which holds the contents of
+ ANT_HOME/lib
. Ant's core and its tasks will be
+ loaded through this classloader and not the bootstrap
+ classloader.
+ This causes some small but notable differences between Ant
+ 1.5.x and 1.6.x. Most importantly, a third-party task that is
+ part of CLASSPATH
will no longer work in Ant
+ 1.6.x since the task now can't find Ant's classes. In a sense
+ this is the same problem this entry is about, only
+ ant.jar
has become the external library in
+ question now.
+ This coreloader also holds the contents of
+ ~/.ant/lib
and any file or directory that has
+ been specified using Ant's -lib
command line
+ argument.
+ Let's see what happens when you load the <junit>
+ task. 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 it fails to find the
+ class using the bootstrap classloader it will try the
+ coreloader next. Again, the coreloader doesn't know anything
+ about your path.
+ If the coreloader can load the class Ant has asked it to
+ load (which it can if ant-junit.jar
is in
+ ANT_HOME/lib
), this class will try to load the
+ external library from coreloader as well - it doesn't
+ know anything else - and will not find it unless the library
+ is in CLASSPATH
or the coreloader as well.
+ To solve this, you have the following major options:
+
+ - put all external libraries you need in
+
CLASSPATH
as well this is not what you want,
+ otherwise you wouldn't have found this FAQ entry.
+
+ - put all external libraries you need in
+
ANT_HOME/lib
or .ant/lib
. This
+ probably still isn't what you want, but you might reconsider
+ the .ant/lib
option.
+
+ - Always start Ant with the
-lib
command line
+ switch and point to your external libraries (or the
+ directories holding them).
+
+ - remove the class that loads the external library from
+ the coreloader.
+
In Ant 1.6 optional.jar
has been split into
multiple jars, each one containing classes with the same
dependencies on external libraries. You can move the
- "offending" jar out of ANT_HOME/lib. For the
+ "offending" jar out of ANT_HOME/lib
. For the
<junit>
task it would be
ant-junit.jar
and for <style>
it would be ant-trax.jar
,
ant-xalan1.jar
or ant-xslp.jar
-
depending on the processor you use.
- If you use the option to break up optional.jar
- for <junit>
or remove
- ant-junit.jar
, you still have to use a
- <taskdef>
with a nested
- <classpath>
to define the junit task.
+ If you do so, you will have to <taskdef>
+ all optional tasks that need the external libary and use
+ nested <classpath>
elements in the
+ <taskdef>
tasks that point to the new
+ location of ant-*.jar
. Also, don't forget
+ to add the new location of ant-*.jar
to the
+ <classpath>
of your
+ <style>
or <junit>
+ task.
+ For example
+
+ <taskdef name="junit"
+ class="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
+ <classpath>
+ <pathelement location="HOME-OF/junit.jar"/>
+ <pathelement location="NEW-HOME-OF/ant-junit.jar"/>
+ </classpath>
+ </taskdef>
+
When running Ant 1.4 on Windows XP and JDK 1.4, I get
diff --git a/xdocs/faq.xml b/xdocs/faq.xml
index 812607814..ca4d094db 100644
--- a/xdocs/faq.xml
+++ b/xdocs/faq.xml
@@ -1346,36 +1346,26 @@ mv /tmp/foo $ANT_HOME/bin/antRun
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.
-
- Technically the sentence above isn't true for Ant 1.6
- and later anymore, but the result is the same. For the sake
- of this discussion, CLASSPATH
and
- ANT_HOME/lib
are identical.
-
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
.
+ that doesn't work unless you put the external library
+ into the CLASSPATH
or place it in
+ ANT_HOME/lib
.
- The root of the problem is that the class that needs the
- external library is on the CLASSPATH
.
+ Some background is necessary before we can discuss
+ solutions for Ant
+ 1.5.x and Ant
+ 1.6.x.
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 most cases - for example using <style> or
+ <junit> - 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
@@ -1400,17 +1390,45 @@ mv /tmp/foo $ANT_HOME/bin/antRun
the parent of a ClassLoader
instance.
-
This means, Ant's class loader will consult the
+
The possible solutions depend on the version of Ant you
+ use, see the next sections.
+
+
+
+
+ <style> or <junit> ignores my
+ <classpath> - Ant 1.5.x version
+
+
+
+ Please read the previous
+ entry before you go ahead.
+
+ First of all let's state that Ant's wrapper script
+ (ant
or ant.bat
) 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.
+
+ The root of the problem is that the class that needs the
+ external library is on the CLASSPATH
.
+
+ Let's see what happens when you load the <junit>
+ task. 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.
+ asked it to load (which it can if optional.jar
is
+ part of CLASSPATH
), 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:
@@ -1423,9 +1441,6 @@ mv /tmp/foo $ANT_HOME/bin/antRun
the CLASSPATH
.