簡體   English   中英

Ant taskdef - 耗盡PermGen空間

[英]Ant taskdef - running out of PermGen space

使用創建子項目(如<antcall><ant> Ant任務可能會因以下錯誤之一而重復調用時導致構建失敗:

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

僅當使用<typedef><taskdef>定義其中一個被調用的任務時才會出現該錯誤,並且在使用與<javadoc>捆綁的任務時不會出現該錯誤。

有沒有辦法避免OutOfMemoryError而不增加最大Java堆大小? 雖然增加堆大小可以工作一段時間,但如果添加更多內存密集型任務,問題仍然會重新出現。


以下示例任務和關聯的build.xml文件在我的Linux機器上導致OutOfMemoryError ,Java堆設置為10 MB(用於測試)。 Ant任務構造一個需要內存的對象(在這種情況下是一個Closure模板大豆模塊的Guice注入器),然后使用<antcall>重復調用<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 在此描述方法我能夠解決內存問題,至少對於您發布的簡單示例代碼。

antcall ,問題在於,每次通過antcall Ant使用taskdef時,Ant都會使用不同的類加載器,因此您antcall就會吃掉你的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文檔中有一個關於antlib命名空間的注釋 ,其中說“在未來的Ant版本中可能會刪除資源在默認類路徑中的要求”。 根據實施方式的不同,未來的解決方案可能會中斷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM