Ant:将编译器参数传递给javac

32

我有一个Ant脚本可以编译:

            <javac srcdir="${test.src.dir}" destdir="${test.dist.dir}">
               ...  
               <compilerarg value="-Xlint:unchecked" />
            </javac>

我需要增加编译器的堆内存,因此我将以下参数放入compileargs中:

<compilerarg value="-Xlint:unchecked -Xms128m -Xmx512m" />

但我在控制台中收到一个错误:

[javac] javac: invalid flag: -Xms128m
[javac] Usage: javac <options> <source files>

为什么会发生这种情况?我该如何增加javac使用的内存?


这是一个复制粘贴错误吗?错误信息中提供的值和实际提供的值(32m/128m)不同? - Alois Cochard
1
也许你需要将每个参数分别传递到单独的<compilerarg />元素中? - ZeissS
@ZeissS:单独的<compilerarg />元素会导致相同的错误,不幸的是。 - Denys Kniazhev-Support Ukraine
3个回答

61

默认情况下,<javac> 与 Ant 在同一进程中运行。Java 的一个普遍限制是,在 JVM 进程启动后,您无法调整该 JVM 进程的 XmsXmx。因此,您看到的错误消息是软件拒绝您试图违反此原则的结果(使用了不友好的错误消息)。

然而,如果您在 <javac> 标签上指定属性 fork="true",则您将能够指定新的 XmsXms。这是因为 fork 指示 Ant 在新的 JVM 子进程中启动 javac。由于 JVM 进程是新的,它为 Ant 提供了一个可以接受的机会来为其指定 XmsXmx


您可以尝试像这样:

<project name="project" default="all" basedir="[yourvalue]">
    <target name="all">
        <javac srcdir="[yourvalue]" destdir="[yourvalue]" fork="true">
            <!-- javac requires that -Xmx and -Xms be prefixed with -J -->
            <compilerarg line="-J-Xms128m -J-Xmx512m" />
        </javac>
    </target>
</project>

(请注意我使用的是compilerarg line=""而不是compilerarg value=""line属性允许您指定多个以空格分隔的参数,而value属性用于传递单个参数。)


Ant将等待分叉的<javac>退出,这发生在javac进程完成其工作(即编译)后。然后,Ant继续在其自己的原始JVM进程中运行构建脚本。Ant将检查分叉的javac是失败还是成功,并根据此信息采取通常的操作。


性能

通常更具性能优势的方法是分叉javac,而是仅为初始Ant JVM整体调整相关的内存设置。这通常是(但并非总是)最佳选择,因为启动单独的JVM通常比允许javac在进程中运行更慢,需要更多的内存。

如果您正在使用Ant提供的ant.batant.sh来启动Ant,则可以通过定义环境变量ANT_OPTS包含要使用的参数来轻松地调整Ant的XmsXmx。设置环境变量的方法有很多种,但您可以直接编辑ant.bat文件:

set ANT_OPTS=-Xms128m -Xmx512m

6
你是否尝试在Java任务下使用<jvmarg value="-Xmx512m" />?对于默认的设置,你可以使用ANT_OPTS环境变量。我找到了这个示例,虽然不是很有用,但其中包含一个build.xml文件。
通过谷歌搜索,我发现可以增加Javac堆空间。
<javac fork="true"
       srcdir="${basedir}/src"
       destdir="${basedir}/build/classes"
       classpath="${project.classpath}"
       memoryinitialsize="256m"
       memorymaximumsize="256m">
</javac>

这段内容来自链接。将fork设置为true非常重要,它与it技术有关。


抱歉,但 jvmargjavac 任务中无效:javac 不支持嵌套的 "jvmarg" 元素。 - Denys Kniazhev-Support Ukraine

2

我认为这个问题并不是与ant相关的。如果直接尝试javac -Xms128m -Xmx512m,你会看到相同的消息。

你需要使用-J选项来直接传递标志给运行时系统。例如:

-J-Xms128m -J-Xmx512m而不是只有-Xms128m -Xmx512m在你的compilerarg中。

javac -X用于向编译器传递非标准选项。如果运行命令javac -X,它将显示一个合法选项列表,其中包括你使用的-Xlint。内存选项是底层JVM的设置,因此需要使用-J

替代方案

对于javac任务,有memoryInitialSize(相当于-Xms)和memoryMaximumSize(相当于-Xmx)选项,因此请尝试使用它们来代替使用compilerargs,例如:

<javac srcdir="${test.src.dir}" destdir="${test.dist.dir}"
  memoryInitialSize="128m"
  memoryMaximumSize="512m">

-J-前缀产生相同的结果:[javac] javac: invalid flag: -J-Xms32m - Denys Kniazhev-Support Ukraine
请尝试我在上面答案中添加的替代解决方案。 - mikej
+1 - 另一种替代方法可行,但我仍然想弄清楚为什么 -Xms32m-J-Xms32m 都不起作用。 - Denys Kniazhev-Support Ukraine
我本身对此很感兴趣。当我从命令行运行javac时,-J-Xms32m适用于我,但在Ant任务中不起作用。我尝试使用-verbose来查看Ant正在执行的命令中的差异,但没有发现任何不同。 - mikej
@mikej 正如所选答案中提到的,我相信需要设置fork="true"才能将-J参数传递给新进程。 - Tim Lewis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接