32

I have ant script that compiles:

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

I need to increase heap memory of compiler, so I've put the following arguments into compileargs:

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

But I get an error in console:

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

Why does it happen? How do I increase memory used by javac?

trincot
  • 317,000
  • 35
  • 244
  • 286

3 Answers3

61

By default, <javac> runs in-process with Ant. It is a general limitation of Java that you can't adjust a JVM process' Xms and Xmx once that JVM process has launched. So, the error message that you are seeing is the software rejecting your attempt to violate this principle (using an unhelpful, unfriendly error message.)

If, however, you specify the attribute fork="true" on the <javac> tag you will be able to specify a new Xms and Xms. This is because fork instructs Ant to launch a new JVM subprocess in which to run javac. Because the JVM process is new, it gives Ant an acceptable opportunity to specify Xms and Xmx for it.


You might try something like this:

<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>

(Notice I am using compilerarg line="" rather than compilerarg value="". The line attribute lets you specify multiple space-separated arguments. The value attribute is for passing a single argument.)


Ant will wait for the forked <javac> to exit, which happens after the javac process finishes its work (i.e. compiling). Ant then continues running the build script inside its own original JVM process. Ant will check if the forked javac failed or succeeded, and take the usual actions based on this information.


Performance

It's usually more performant to not fork javac, and instead simply tune the relevant memory settings for the initial Ant JVM overall. This is often (but not always) the best choice because launching a separate JVM is usually slower and takes more memory than simply allowing javac to run in-process.

If you are using the Ant-provided ant.bat or ant.sh to launch Ant, an easy way to tune Ant's Xms and Xmx is to define the environment variable ANT_OPTS to contain the arguments you want. There many ways to set environment variables, but you could just edit ant.bat:

set ANT_OPTS=-Xms128m -Xmx512m
Mike Clark
  • 10,027
  • 3
  • 40
  • 54
6

Have you tried <jvmarg value="-Xmx512m" /> under Java task? For default ones you can use ANT_OPTS environment variable. I found this example, not very useful but has a build.xml.

To increase Javac heap space I found this while googling.

<javac fork="true"
       srcdir="${basedir}/src"
       destdir="${basedir}/build/classes"
       classpath="${project.classpath}"
       memoryinitialsize="256m"
       memorymaximumsize="256m">
</javac>

It's copied from this link. Setting fork to true is important.

CoolBeans
  • 20,654
  • 10
  • 86
  • 101
2

I don't think this problem is really related to ant. You would see the same message if you tried javac -Xms128m -Xmx512m directly.

You need to use the -J option for passing flags directly to the runtime system. e.g.

-J-Xms128m -J-Xmx512m instead of just -Xms128m -Xmx512m in your compilerarg.

javac -X is for passing nonstandard options to the compiler. If you run the command javac -X it will display a list of legal options which include the -Xlint that you've used. The memory options are settings for the underlying JVM, hence the need to use -J.

Alternative

There are memoryInitialSize (equivalent to -Xms) and memoryMaximumSize (equivalent to -Xmx) options for the javac task so try those instead of using compilerargs e.g.

<javac srcdir="${test.src.dir}" destdir="${test.dist.dir}"
  memoryInitialSize="128m"
  memoryMaximumSize="512m">
mikej
  • 65,295
  • 17
  • 152
  • 131
  • The `-J-` prefix yields to the same results: `[javac] javac: invalid flag: -J-Xms32m` – Denys Kniazhev-Support Ukraine Nov 09 '10 at 14:52
  • Please try the alternative solution that I've added to the answer above. – mikej Nov 09 '10 at 15:18
  • +1 - Alternative way worked, but still I would like to figure out why not `-Xms32m` neither `-J-Xms32m` didn't work – Denys Kniazhev-Support Ukraine Nov 09 '10 at 15:27
  • I am interested in this myself. `-J-Xms32m` works for me when running `javac` from the command line but not from the Ant task. I've tried using `-verbose` with Ant to see if I can spot the difference in the commands being executed but couldn't see anything. – mikej Nov 09 '10 at 15:46
  • @mikej as mentioned in the chosen answer, I believe fork="true" needs to be set for it to pass the -J parameters to a new process. – Tim Lewis Mar 06 '12 at 22:04