You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@ant.apache.org by Xu Xin <an...@gmail.com> on 2007/05/09 17:20:54 UTC
The AntClassLoader created in one JUnitTask can not be used in another.
Hello everyone,
I had a problem with JUnitTask, I have a couple of xml files where I also
have a lot of targets which contain <junit> tasks, originally I used the
Apache Ant's JUnitTask, but unfortunately the test run had performance
issue, that was caused by each <test> has its own classloader, as a result
some static memory was created multiple times.
So I customized the JUnitTask by making the classloader created for each
test cacheable, the <junit> task has the same customer classpath elements
share the same classloader, so I can save the memory as I can, but the
strange thing is junit testcase was not recognized, it seemed a
classloading issue, but after I ran the tests in DEBUG mode, I can find the
classloader hierarchy is correct, I do not know what's going wrong. The
snippet code is below:
private void createClassLoader() {
Path userClasspath = getCommandline().getClasspath();
if (userClasspath != null) {
//get cached classloader from the pool if it exists
classLoader = getCachedClassLoader(userClasspath);
Path classpath = (Path) userClasspath.clone();
if (includeAntRuntime) {
log("Implicitly adding " + antRuntimeClasses + " to CLASSPATH",
Project.MSG_VERBOSE);
classpath.append(antRuntimeClasses);
}
if (reloading || classLoader == null) {
//create a new one if no cached
classLoader = getProject().createClassLoader(classpath);
if (getClass().getClassLoader() != null
&& getClass().getClassLoader() != Project.class.getClassLoader())
{
classLoader.setParent(getClass().getClassLoader());
}
classLoader.setParentFirst(false);
classLoader.addJavaLibraries();
// make sure the test will be accepted as a TestCase
classLoader.addSystemPackageRoot("junit");
// will cause trouble in JDK 1.1 if omitted
classLoader.addSystemPackageRoot("org.apache.tools.ant");
// testlogic: this fixes 'not a JUnitResultFormatter' issue
classLoader.addSystemPackageRoot("org.testlogic.testrunner.ant.junit
");
cacheClassLoader(userClasspath, classLoader);
} else {
//this is the cached one
if (classLoader != null) {
classLoader.setProject(this.getProject());
classLoader.setClassPath(classpath);
if (getClass().getClassLoader() != null
&& getClass().getClassLoader() != Project.class.getClassLoader())
{
classLoader.setParent(getClass().getClassLoader());
}
}
}
}
}
and next pass the classLoader to JUnitTestRunner as usual, the test class
can be loaded, as well as JUnit class: TestSuite and Test, but when
constructing TestCase, TestSuite complains the test class is not
implementation of Test, but I can see the test class was loaded by cached
AntClassLoader, and TestSuite and Test were loaded by its parent
classloader. So could you guys please tell me what's wrong?
Thanks
--
anfernee
Re: The AntClassLoader created in one JUnitTask can not be used in
another.
Posted by Steve Loughran <st...@apache.org>.
Xu Xin wrote:
> Hello everyone,
>
> I had a problem with JUnitTask, I have a couple of xml files where I also
> have a lot of targets which contain <junit> tasks, originally I used the
> Apache Ant's JUnitTask, but unfortunately the test run had performance
> issue, that was caused by each <test> has its own classloader, as a result
> some static memory was created multiple times.
>
> So I customized the JUnitTask by making the classloader created for each
> test cacheable, the <junit> task has the same customer classpath elements
> share the same classloader, so I can save the memory as I can, but the
> strange thing is junit testcase was not recognized, it seemed a
> classloading issue, but after I ran the tests in DEBUG mode, I can find the
> classloader hierarchy is correct, I do not know what's going wrong. The
> snippet code is below:
>
>
>
> and next pass the classLoader to JUnitTestRunner as usual, the test class
> can be loaded, as well as JUnit class: TestSuite and Test, but when
> constructing TestCase, TestSuite complains the test class is not
> implementation of Test, but I can see the test class was loaded by cached
> AntClassLoader, and TestSuite and Test were loaded by its parent
> classloader. So could you guys please tell me what's wrong?
> Thanks
My recommendation would be to avoid these things; its very easy to leak
classes by sharing a classloader.
Just fork the junit run with fork="once" in your <junit> task
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
For additional commands, e-mail: user-help@ant.apache.org