Ant taskdef - exit PermGen space

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;

/** Custom Ant task that constructs a Guice injector. */
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
+5
source share
1 answer

Using the Keith Gregory method described here I was able to bypass the memory, at least for the simple code that you posted.

, , taskdef antcall Ant, , . , , - - .

- taskdef antlib antlib . Ant . Ant.

, ( memtest), , antlib.xml , :

<antlib>
  <taskdef name="create-injector" classname="memtest.CreateGuiceInjectorTask" />
</antlib>

buildfile

<project name="out-of-memory-test" basedir="." default="test" xmlns:mt="antlib:memtest">

<target name="call-create-injector">
  <mt:create-injector />
</target>

, Ant. antcalls, - , .

Ant antlib, : ", , Ant." , , .

+5

All Articles