OutOfMemoryError creating clover-snapshot in Ant running from QuickBuild

447 views Asked by At

I have a QuickBuild server (5.0.14). This is running a build step using ant.

The Ant target looks like this:

<target name="clover-snapshot" depends="with-clover">
  <clover-snapshot file="${clover.snapshot.file}"/>
</target>

We are using Clover Version 3.1.5.

This step is failing with the following stacktrace:-

java.lang.OutOfMemoryError: Java heap space
    at com.cenqua.clover.util.CloverBitSet.read(CloverBitSet.java:71)
    at com.cenqua.clover.PerTestRecordingTranscript.read(PerTestRecordingTranscript.java:45)
    at com.cenqua.clover.RecordingTranscripts.readSliceFromDisk(RecordingTranscripts.java:124)
    at com.cenqua.clover.RecordingTranscripts$FileRef.read(RecordingTranscripts.java:354)
    at com.cenqua.clover.CoverageDataCollator.collatePerTestRecordings(CoverageDataCollator.java:156)
    at com.cenqua.clover.CoverageDataCollator.loadCoverageData(CoverageDataCollator.java:68)
    at com.cenqua.clover.CloverDatabase.loadCoverageData(CloverDatabase.java:164)
    at com.cenqua.clover.CloverDatabase.loadCoverageData(CloverDatabase.java:159)
    at com.cenqua.clover.CloverDatabase.loadWithCoverage(CloverDatabase.java:283)
    at com.cenqua.clover.tasks.CloverSnapshotTask.cloverExecute(CloverSnapshotTask.java:51)
    at com.cenqua.clover.tasks.AbstractCloverTask.execute(AbstractCloverTask.java:55)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
    at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:392)
    at org.apache.tools.ant.Target.performTasks(Target.java:413)
    at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
    at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
    at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
    at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
    at org.apache.tools.ant.Main.runBuild(Main.java:811)
    at org.apache.tools.ant.Main.startAnt(Main.java:217)
    at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
    at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

I take it from the call to invoke() in the above that Clover is being called reflectively within the JVM used by Ant.

As such, I have attempted to allocate more heap space to the Ant JVM. I did this by editing the build step in QuickBuild and specifying the following environment variable:-

ANT_OPTS is set to -Xmx1024m -Xms512m

This has not solved the issue. (I plucked these numbers out of the air, the max size was not calculated in any sort of way.)

My question is, how can I allocate additional heap space to Clover to allow it to execute without running out of memory. Or alternatively, what can I do to confirm these settings are being used?

3

There are 3 answers

0
Renat Gilmanov On

It looks like you did everything correctly. ANT_OPTS is the right way to solve this problem. I've used pretty much the same approach to solve similar problem. Did you use 64-bit JVM? Did you see that space has been actually allocated?

Anyway, there is a good instruction:

enter image description here

I would also suggest to use VisualVM in order to verify JVM has been created properly and identify the actual cause.

0
Ben Poulson On

There are two way to increase memory size for ant:

  1. Setting the value of ANT_OPTS property in environment var. For example:
    set ANT_OPTS=-Xms256m -Xmx1024m -XX:MaxPermSize=120m

  2. Specifying maxmeory attribute in in ant Java target. For example:

<target name="MergingHugeJars"> 
    <echo message="Merging jars ${InputJars} into ${OutputJar}"/>
    <java jvm="${JVM}" classname="com.krishna.test.MergeHugeJars" fork="true" failonerror="true" maxmemory="512m" > 
        <arg line="${OutputJar} ${InputJars}"/>
    </java>
</target> 

You can fiddle with the maxmemory="512m" section of the third line.

1
dwurf On

You can use jstat to attach to a running java process and see if your settings are being used:

$ jstat -gccapacity 19726
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC 
 42560.0 681984.0  42560.0 5312.0 5312.0  31936.0    85248.0  1363968.0    85248.0    85248.0  21248.0 169984.0  21248.0  21248.0      0     0

Xmx is the combination of NGCMX and OGCMX. In english, the maximum heap size you specify via -Xmx is split between the Old generation and New generation.

A quick little script to format this information nicely:

jcmd | grep -v JCmd | while read pid name; do echo -n "Xmx for $name "; jstat -gccapacity $pid | sed '1d' | awk '{ print $2 + $8 " MB" }'; done
Xmx for org.example.MyClass 2045952 MB