Using Ant tasks that create subprojects, such as <antcall>and <ant>, can cause build failures when called again due to one of the following errors:
- java.lang.OutOfMemoryError: PermGen space
- java.lang.OutOfMemoryError: Java heap space
An error occurs only when one of the tasks being called is defined with <typedef>or <taskdef>and does not appear when using tasks related to Ant, such as <javadoc>.
Is there a way to avoid OutOfMemoryErrorwithout increasing the maximum Java heap size? Although an increase in heap size works for while a problem still arises if additional memory intensive tasks are added.
The following example task and its associated file build.xmlare called
OutOfMemoryErroron my Linux box with a bunch of Java set to 10 MB (for testing). The Ant task creates a memory-dependent object (in this case, the Guice injector for the soy module of the closure pattern), which is then repeatedly called using <antcall>.
CreateGuiceInjectorTask.java
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.template.soy.SoyModule;
import org.apache.tools.ant.Task;
public final class CreateGuiceInjectorTask extends Task {
private Injector injector;
public CreateGuiceInjectorTask() {
injector = Guice.createInjector(new SoyModule());
}
public void execute() {
System.out.println("Constructed Guice injector...");
}
}
build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="out-of-memory-test" basedir=".">
<property name="build.dir" location="${basedir}/build" />
<property name="CreateGuiceInjectorTask.jar"
location="${build.dir}/CreateGuiceInjectorTask.jar" />
<taskdef name="create-injector"
classname="CreateGuiceInjectorTask"
classpath="${CreateGuiceInjectorTask.jar}" />
<target name="call-create-injector">
<create-injector />
</target>
<target name="test"
description="Create multiple injectors until out of memory">
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
<antcall target="call-create-injector" />
</target>
</project>
Test Output:
$ ant test
test:
call-create-injector:
[create-injector] Constructed Guice injector...
call-create-injector:
[create-injector] Constructed Guice injector...
...
call-create-injector:
BUILD FAILED
Could not create type create-injector due to java.lang.OutOfMemoryError: Java heap space
source
share