首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ant耗尽PermGen空间

Ant耗尽PermGen空间
EN

Stack Overflow用户
提问于 2012-05-19 05:36:32
回答 1查看 5K关注 0票数 4

使用创建子项目(如<antcall><ant> )的Ant任务,当由于以下错误之一反复调用时,可能会导致构建失败:

  • java.lang.OutOfMemoryError: PermGen空间
  • java.lang.OutOfMemoryError: Java堆空间

只有在使用<typedef><taskdef>定义了被调用的任务时才会出现错误,而在使用与Ant捆绑的任务(如<javadoc> )时则不会出现错误。

是否有一种避免OutOfMemoryError而不增加最大Java堆大小的方法?虽然增加堆大小可以工作一段时间,但如果增加更多内存密集型任务,问题仍然会再次出现。

下面的示例任务和相关的build.xml文件在我的Linux上导致一个OutOfMemoryError,将Java堆设置为10 MB (用于测试)。Ant任务构造一个需要内存的对象(在本例中是闭包模板Soy的Guice注入器),然后使用<antcall>反复调用该对象。

CreateGuiceInjectorTask.java

代码语言:javascript
复制
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

代码语言:javascript
复制
<?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>

测试输出:

代码语言:javascript
复制
$ 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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-19 12:34:37

使用描述基思·格雷戈里这里方法,我能够解决内存问题,至少对于您发布的简单示例代码是这样的。

概括地说,问题在于每次通过antcall使用taskdef时,Ant都使用不同的类加载器,因此您很快就会消耗掉您的permgen。要确认这一点,您可以修改类以打印类加载器哈希代码--您将在每次迭代中看到它的不同。

解决方法是将taskdef打包为一个安特利布,并使用antlib命名空间加载它。其结果是使用了Ant自己的类加载器。为此,您必须将类放在Ant类路径上。

为了测试这一点,我将测试类放在一个包命名空间(称为memtest)中,进行编译,然后在包目录中添加一个antlib.xml,如下所示:

代码语言:javascript
复制
<antlib>
  <taskdef name="create-injector" classname="memtest.CreateGuiceInjectorTask" />
</antlib>

将buildfile项目声明更改为

代码语言:javascript
复制
<project name="out-of-memory-test" basedir="." default="test" xmlns:mt="antlib:memtest">

而目标是

代码语言:javascript
复制
<target name="call-create-injector">
  <mt:create-injector />
</target>

为了进行测试,我将所需的所有内容都放在Ant类路径上。它成功地运行了许多反调用,类加载器哈希代码的调试打印确认使用了预期的单个实例。

antlib命名空间的Ant文档中有一条注释说:“在未来版本的Ant中,可能会删除资源在默认类路径中的要求。”这取决于如何实现,工作可能会在未来中断。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10662614

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档