2

I did the following test:

code

public class FooMain {
   public static void main(String args[]) throws ClassNotFoundException {
      Class klass = Class.forName("com.sun.xml.internal.ws.spi.ProviderImpl");
   }
}

$CLASSPATH environment variable

echo $CLASSPATH
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/rt.jar:.
jar tvf /usr/lib/jvm/java-7-openjdk-i386/jre/lib/rt.jar | grep com.sun.xml.internal.ws.spi.ProviderImpl

 1742 Wed Oct 24 18:52:52 EEST 2012 com/sun/xml/internal/ws/spi/ProviderImpl$1.class
 1349 Wed Oct 24 18:52:52 EEST 2012 com/sun/xml/internal/ws/spi/ProviderImpl$2.class
12412 Wed Oct 24 18:52:52 EEST 2012 com/sun/xml/internal/ws/spi/ProviderImpl.class

So the sought class is on the $CLASSPATH.

However running the above code with Ant's java task and fork set to "false" fails and only succeeds if fork is set to "true".

This is however is against what's written in the ANT in Action book where it is noted in pg. 152 that the basic Ant's java task runs with the Ant classpath which includes, among, other things, "everything in the CLASSPATH environment variable".

So why can't Ant's java task find the sought-for class when fork is set to "false" and succeeds only if fork is set to "true" even when the class is on the $CLASSPATH in both cases?

Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331

2 Answers2

4

With fork="false" the <java> task uses a special "isolated" classloader that loads classes only from the task's own classpath (the classpathref attribute or <classpath> nested element), except for a specific set of hard-coded package prefixes which it will attempt to load from the parent loader if they are not found on the task's own classpath. Since com.sun.xml isn't on this hard-coded list it will not be delegated to the parent and so will give you a ClassNotFoundException.

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
  • 1
    Is there a way to turn that "isolation" off while keeping ```fork="false```? I found myself in a need to execute java task using current ant classpath with an addition of a couple of extra jars. Or is there, perhaps, a way to assemble new classpath by joining current ant classpath with the jars that I need? – Andrei LED Jun 02 '17 at 16:01
3

The manual page has the following explanation for the operation of the java task:

Executes a Java class within the running (Apache Ant) VM or forks another VM if specified.

If odd things go wrong when you run this task, set fork="true" to use a new JVM.

Use ANT to manage the classpath

I would highly advise that you always fork the JVM and take advantage of ANT classpath management facilities:

<path id="runtime.path">
    <fileset dir="lib/runtimejars" includes="*.jar"/>
</path>

<java classname="???" fork="true" classpathref="runtime.path">
    <arg line="arg1 arg2 arg3"/>
</java>

Why? If you port your build to another machine you can't be certain that the CLASSPATH variable is setup the same way.

Executable jar

Another way to reduce your dependence on the CLASSPATH variable is to create an executable jar. The following answers demonstrate how to use the manifestclasspath task to create a classpath which you can embed within you jar's manifest:

Community
  • 1
  • 1
Mark O'Connor
  • 76,015
  • 10
  • 139
  • 185