Sunday, August 29, 2010

How to fix "OutOfMemoryError: PermGen space" errors when running Cobertura from Maven2

Recently while working on a project, I was faced with ugly OutOfMemoryError being thrown while running cobertura.

We used Maven2 as the build tool on the project.

I tried various things to fix it but without luck.

A few of those were:

  • Setting the MAVEN_OPTS=-Xms512m -Xmx1024m -XX:MaxPermSize=512m
  • Setting the JVM_OPTS=-Xms512m -Xmx1024m -XX:MaxPermSize=512m
  • Trying the <maxmem> property of cobertura in pom.xml
None of them fixed the issue.

The real problem is surefire plug-in forks a new jvm to run the tests and this jvm does not seem to inherit the memory settings.

So what is the way around is?

We can use the argLine configuration property of the maven-surefire-plugin to bump up the memory.

The above code means:

  • Initial java heap size is 512m
  • Maximum java heap size is 1024m 
  • Maximum size of permanent generation heap is 512m.  
Basically all we are doing is bumping up the memory used by the surefire plugin to run the tests.

All said and done, the real test is in the real world.

After those settings I ran mvn clean cobertura:cobertura and Yes, it worked!

No more OutOfMemoryError!

The sample pom.xml that I used is:

Have fun!

14 comments:

  1. Should this change need to be done in all the pom.xml in the project

    ReplyDelete
  2. Well I have not tried with multiple pom's, but if I had to take a guess the answer would be YES.

    Logically speaking, maven-surefire-plugin forks a JVM for the test run. Which means that if you have two modules which run cobertura coverage report, both of them will fork a different JVM for running the tests. Hence, if you did these settings at only one place then, may be, reports will be generated for one module, but would fail for the other module. This would mean that you will have to do these settings in all places where maven-surefire-plugin is used.

    ReplyDelete
  3. I've been running into this problem for a day now, and had a hard time figuring out what the problem was. I knew I wasn't forking processes, or at least I thought so.
    After applying your fix, I looked at the documentation and realized the default is forkMode=once.

    ReplyDelete
  4. It is <argLine> and not <argline>. The posted examples are not valid xml.

    ReplyDelete
  5. Lee,

    Thanks for pointing out the typo. Yes, its argLine and not argline. Post updated.

    Thanks & Regards

    Deep Shah

    ReplyDelete
  6. Rahul,

    Glad that it worked out for you.

    ReplyDelete
  7. Thanks - was going a bit nuts tracking this one down!

    ReplyDelete
  8. Awesome! This really helped me out.

    ReplyDelete
  9. Thanks alot Deep Shah!

    ReplyDelete
  10. You just need to use JAVA_OPTS.
    Here is an example of setting it for just that win shell where you are going to run your tests. All

    set JAVA_OPTS=-Xmx1G -Xms256m -XX:MaxPermSize=256m

    ReplyDelete
    Replies
    1. JAVA_OPTS do not work in this case.
      But the pom solution helped me.

      Delete
  11. Thanks Deep. Your post helped us today. Before we implemented this change, we were getting various OOM and PermGen errors in our build when doing integration tests. I tried setting the MAVEN_OPTs with the memory settings but was getting different results each time I ran the build.

    -Richard Yee

    ReplyDelete

Have some Fun!