使用创建子项目(如<antcall>和<ant> )的Ant任务,当由于以下错误之一反复调用时,可能会导致构建失败:
只有在使用<typedef>或<taskdef>定义了被调用的任务时才会出现错误,而在使用与Ant捆绑的任务(如<javadoc> )时则不会出现错误。
是否有一种避免OutOfMemoryError而不增加最大Java堆大小的方法?虽然增加堆大小可以工作一段时间,但如果增加更多内存密集型任务,问题仍然会再次出现。
下面的示例任务和相关的build.xml文件在我的Linux上导致一个OutOfMemoryError,将Java堆设置为10 MB (用于测试)。Ant任务构造一个需要内存的对象(在本例中是闭包模板Soy的Guice注入器),然后使用<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>测试输出:
$ 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发布于 2012-05-19 12:34:37
使用描述基思·格雷戈里的这里方法,我能够解决内存问题,至少对于您发布的简单示例代码是这样的。
概括地说,问题在于每次通过antcall使用taskdef时,Ant都使用不同的类加载器,因此您很快就会消耗掉您的permgen。要确认这一点,您可以修改类以打印类加载器哈希代码--您将在每次迭代中看到它的不同。
解决方法是将taskdef打包为一个安特利布,并使用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类路径上。它成功地运行了许多反调用,类加载器哈希代码的调试打印确认使用了预期的单个实例。
antlib命名空间的Ant文档中有一条注释说:“在未来版本的Ant中,可能会删除资源在默认类路径中的要求。”这取决于如何实现,工作可能会在未来中断。
https://stackoverflow.com/questions/10662614
复制相似问题