1

I own a Play 2.2.X application.

I was running a suite of specs using Specs2 that ended up to an Out Of Memory regarding permgen space.

Then I just placed this setting in my Build.scala:

sbt.Keys.fork in Test := false

and it works now like a charm.

According to some documentations, Play 2.X forks test by default in order to prevent memory leaks but I really observe the exact contrary.

What could be the reason(s) for observing permgen issues when forking tests? I just don't figure it out.

UPDATE -------------- With this configuration:

parallelExecution in Test := false,
javaOptions in (Test,run) ++= Seq("-Xms512M", "-Xmx2048M", "-XX:MaxPermSize=2048M", "-XX:+CMSClassUnloadingEnabled")

Here's the error I obtain when forking is enabled:

Uncaught exception when running htmlreporting.AllSpecs: java.lang.OutOfMemoryError: PermGen space
sbt.ForkMain$ForkError: PermGen space
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at scala.collection.parallel.immutable.LazyParVectorCombiner.result(ParVector.scala:129)
    at scala.collection.parallel.immutable.LazyParVectorCombiner.result(ParVector.scala:105)
    at scala.collection.Parallelizable$class.par(Parallelizable.scala:42)
    at scala.collection.AbstractTraversable.par(Traversable.scala:105)
    at org.specs2.reporter.AllExporting$$anonfun$export$1$$anonfun$2.apply(AllExporting.scala:28)
    at org.specs2.reporter.AllExporting$$anonfun$export$1$$anonfun$2.apply(AllExporting.scala:27)
    at scalaz.syntax.IdOps$class.$bar$greater(IdOps.scala:15)
    at scalaz.syntax.ToIdOps$$anon$1.$bar$greater(IdOps.scala:82)
    at org.specs2.reporter.AllExporting$$anonfun$export$1.apply(AllExporting.scala:32)
    at org.specs2.reporter.AllExporting$$anonfun$export$1.apply(AllExporting.scala:24)
    at scalaz.syntax.IdOps$class.$bar$greater(IdOps.scala:15)
    at scalaz.syntax.ToIdOps$$anon$1.$bar$greater(IdOps.scala:82)
    at org.specs2.reporter.AllExporting$class.report(AllExporting.scala:17)
    at org.specs2.reporter.SbtConsoleReporter.report(SbtReporter.scala:20)
    at org.specs2.runner.SbtRunner.org$specs2$runner$SbtRunner$$specificationRun(SbtRunner.scala:75)
    at org.specs2.runner.SbtRunner$$anonfun$newTask$1$$anon$5.execute(SbtRunner.scala:59)
    at sbt.ForkMain$Run.runTest(ForkMain.java:239)
    at sbt.ForkMain$Run.runTestSafe(ForkMain.java:211)
    at sbt.ForkMain$Run.runTests(ForkMain.java:187)
    at sbt.ForkMain$Run.run(ForkMain.java:251)

That works well when my conf becomes:

    parallelExecution in Test := false,
    sbt.Keys.fork in Test := false,  //here's the important setting
    javaOptions in (Test,run) ++= Seq("-Xms512M", "-Xmx2048M", "-XX:MaxPermSize=2048M", "-XX:+CMSClassUnloadingEnabled")
Mik378
  • 21,881
  • 15
  • 82
  • 180
  • 1
    Which JVM was it that ran out of permgen, the one SBT was running in or the forked JVM for the tests? – johanandren May 14 '14 at 07:29
  • @johanandren What is the easy way to check that? I copied/pasted my error obtained. I supposed this is the SBT JVM that has crashed since the initial method is called `sbt.ForkMain$Run.run` – Mik378 May 14 '14 at 08:57

1 Answers1

1

Wow I strictly don't understand :) :

I replaced this setting:

javaOptions in (Test,run) ++= Seq("-Xms512M", "-Xmx2048M", "-XX:MaxPermSize=2048M", "-XX:+CMSClassUnloadingEnabled"),

by this:

javaOptions ++= Seq("-Xms512M", "-Xmx2048M", "-XX:MaxPermSize=2048M", "-XX:+CMSClassUnloadingEnabled"),  //without (Test,run) and it works

and it now works !

Why?...Is there another specific group than Test and Run?

Mik378
  • 21,881
  • 15
  • 82
  • 180
  • 1
    There's no `Run`, but `run` since the former could be a configuration (but it's not) with the latter being a task. There are `Compile`, `Runtime` and few other already-available configurations - see http://www.scala-sbt.org/release/docs/Getting-Started/Scopes.html#scoping-by-configuration-axis. – Jacek Laskowski May 14 '14 at 10:02
  • 1
    BTW, your question should really be another SO question (but given your reputation you know it already :)) – Jacek Laskowski May 14 '14 at 10:04
  • Also, I don't think just placing *"this setting in my Build.scala"* would have any effect unless it'd a part of a project (via `settings` method call). – Jacek Laskowski May 14 '14 at 10:05
  • @JacekLaskowski Yes you're absolutely right. I just wanted to be a little fast in answering my own question, not my habit :( . I will create a complete another question relating this trick. (Of course, the "placed settings" is in the `settings` context of my `project`, not in the air :)). – Mik378 May 14 '14 at 10:16
  • Would you mind showing the entire build definition - any `*.sbt` files + `project/*.scala` files + `project/*.sbt`? I think sharing the project on GitHub would make answering your question so much easier. – Jacek Laskowski May 14 '14 at 10:36
  • @JacekLaskowski Thanks for paying attention :) Here's my related new question: http://stackoverflow.com/questions/23652441/forking-tests-is-fine-unless-javaoptions-is-misconfigured I exposed all my concerned files with SBT. – Mik378 May 14 '14 at 10:47