使用创建子项目(例如<antcall>
和<ant>
)的Ant任务可能会因以下错误之一而重复调用时导致构建失败:
仅当使用<typedef>
或<taskdef>
定义其中一个被调用任务时才会出现此错误,并且在使用与<javadoc>
捆绑的任务时不会出现此错误。
有没有办法避免OutOfMemoryError
而不增加。{1}}
最大Java堆大小?虽然增加堆大小适用于
然而,如果添加更多内存密集型任务,问题仍然会重新出现。
以下示例任务和关联的build.xml
文件导致
我的Linux机器上的OutOfMemoryError
,Java堆设置为10 MB(for
测试)。 Ant任务构造了一个需要内存的对象(在本例中是一个Guice
用于闭合模板大豆模块的注射器,然后重复调用
使用<antcall>
。
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...");
}
}
<?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>
$ 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
答案 0 :(得分:5)
使用Keith Gregory's描述的方法here我能够解决内存问题,至少对于您发布的简单示例代码。
问题在于,每次通过antcall
Ant使用taskdef都会使用不同的类加载器,因此您很快就会吃掉你的permgen。要确认这一点,您可以修改您的类以打印类加载器哈希代码 - 您将在每次迭代时看到它的不同。
解决方法是将taskdef打包为antlib并使用antlib命名空间加载它。结果是使用了Ant自己的类加载器。为此,您必须将该类放在Ant类路径上。
为了测试这个,我将测试类放在一个包名称空间(称为memtest)中,编译,然后在包目录中添加一个antlib.xml,如下所示:
<antlib>
<taskdef name="create-injector" classname="memtest.CreateGuiceInjectorTask" />
</antlib>
构建文件项目声明已更改为
<project name="out-of-memory-test" basedir="." default="test" xmlns:mt="antlib:memtest">
和目标
<target name="call-create-injector">
<mt:create-injector />
</target>
测试我把所有需要的东西放在Ant类路径上。它成功运行了许多antcall,并且类加载器哈希码的调试打印确认了使用了预期的单个实例。
Ant documentation for the antlib namespace中有一条说明“在未来的Ant版本中可能会删除资源在默认类路径中的要求。”根据实施方式的不同,未来的解决方案可能会中断。