Wednesday, March 7, 2012

Maven and Out of Memory PermGen space

We are working on a java project building a web app using standard libraries like Spring, Hibernate, Commons, ActiveMQ etc. As common practice we follow TDD and have written lot of integration tests for the application, after writing more and more active mq integration tests, maven started choking while running tests with OutOfMemory PermGen space error. We first thought its our application code which is causing the error, then isolated the problem to the integration tests (especially those active mq tests).

Tried all possible suggestions available over net like the rest who faced a similar problem by increasing the PermGenSize, tweaking JVM options like -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled, in spite of setting high memory options tests were running out of memory with permgen space. Tried profiling the maven process using yourkit and what not but with no luck.

JVM uses 64MB as a default PermGen space and ActiveMQ (especially if you are using in-memory) needs more memory than the default, we were aware of this but were clue less why maven was choking even after setting high memory JVM options. Finally google the best friend of developers came to rescue, we figured out that maven's surefire plugin which is the default plugin which runs tests spawns a new process for running them. So what ?? the memory options should have been inherited from JAVA_OPTS or MAVEN_OPTS environment variables isn't it ? thats what we assumed and we were wrong.

Surefire plugin by default does not inherit the parent processes java options neither does it take the options from the environment variables like JAVA_OPTS or MAVEN_OPTS. To set any jvm option for surefire plugin, it has to be configured in maven pom file.

There is a argLine element which helps you do set jvm opts for surefire plugin. It has to be configured like <argLine> -Xmx512m -XX:MaxPermSize=256m</argLine>  under the configuration section of surefire plugin. This did the trick.


Francesco Pagnamenta said...

Thank you! Had the same problem.


Vibin said...

Thanks a lot!! Saved a lot of time...

Josh Cain said...

One reason why the class unloading argument may not have worked for you is that you also have to have the UseConcMarkSweepGC flag set for the JVM to pick it up.

See this link for more info.

Alberto said...

This is nuts ;) Thanks, at least some info in internet that actually works ;)

Unknown said...

I spent more than a week trying figure out the problem. And then found your article. Oh this surefire plugin.. Thank you so much!