gpt4 book ai didi

java - Ant taskdef - PermGen 空间用完

转载 作者:搜寻专家 更新时间:2023-11-01 02:30:28 26 4
gpt4 key购买 nike

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

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

仅当调用的任务之一是使用 <typedef> 定义时才会发生错误或 <taskdef>并且在使用与 Ant 捆绑在一起的任务时不会出现,例如 <javadoc> .

有没有办法避免 OutOfMemoryError不增加最大 Java 堆大小?虽然增加堆大小适用于同时,如果添加更多内存密集型任务,问题仍然会再次出现。


以下示例任务与build.xml相关联文件导致 OutOfMemoryError在我的 Linux 机器上,Java 堆设置为 10 MB(对于测试)。 Ant 任务构造一个内存消耗大的对象(在本例中是一个 Guice封闭模板大 bean 模块的注入(inject)器),然后重复调用使用 <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

最佳答案

使用 Keith Gregory's方法描述here我能够解决内存问题,至少对于您发布的简单示例代码而言。

概括地说,问题是每次您通过 antcall 使用 taskdef 时,Ant 使用不同的类加载器,因此您会立即吃掉您的 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 类路径中。它成功运行了许多 antcalls,并且类加载器哈希码的调试打印确认使用了预期的单个实例。

Ant documentation for the antlib namespace 中有一条注释上面写着“资源位于默认类路径中的要求可能会在 Ant 的 future 版本中删除”。根据实现方式的不同,变通办法将来可能会中断。

关于java - Ant taskdef - PermGen 空间用完,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10662614/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com