I have a program with a large immutable object that returns a modified version of itself when performing a certain operation. I try to test it in the sbt console, doing something like var myObj = getInitialObject(); and then repeatedly calling myObj = myObj.getNewOne();
There is no reference left to the old object, but the memory doesn't seem to get freed. Eventually I get an OutOfMemoryError: GC overhead limit exceeded. I was able to reproduce the problem with a simple example at a scala repl prompt:
scala> val foo = List.fill(1000000) { new Object() } foo: List[java.lang.Object] = List(java.lang.Object@14fd510, java.lang.Object@202d0e1c, java.lang.Object@6df960c4, java.lang.Object@f401c44, java.lang.Object@39ffbc2e, java.lang.Object@449b8dc1, java.lang.Object@40779d17, java.lang.Object@6cea7211, java.lang.Object@13e6f1f4, java.lang.Object@1f16d461, java.lang.Object@13d13c39, java.lang.Object@dc8cc59, java.lang.Object@79dfee20, java.lang.Object@5c8ab562, java.lang.Object@168a6465, java.lang.Object@57c52e72, java.lang.Object@526c6b62, java.lang.Object@4bfe1934, java.lang.Object@1728cbe6, java.lang.Object@776274ea, java.lang.Object@60e9ebe1, java.lang.Object@1d7d327c, java.lang.Object@67d7a04, java.lang.Object@17d59ff0, java.lang.Object@49f751c9, java.lang.Object@c1a890f, java.lang.Object@221c3dfe, java.lang.Object@6c2a0030, java.lang.O... scala> val foo = List.fill(1000000) { new Object() } foo: List[java.lang.Object] = List(java.lang.Object@6e8fb561, java.lang.Object@1ccd2bfc, java.lang.Object@6202bc29,.... (ommiting the rest of the output) scala> val foo = List.fill(1000000) { new Object() } .... repeat a few more times and get: scala> val foo = List.fill(1000000) { new Object() } null java.lang.OutOfMemoryError: GC overhead limit exceeded at scala.tools.nsc.transform.SpecializeTypes$$anonfun$13.apply(SpecializeTypes.scala:669) at scala.tools.nsc.transform.SpecializeTypes$$anonfun$13.apply(SpecializeTypes.scala:667) at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:200) at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:200) at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59) at scala.collection.immutable.List.foreach(List.scala:45) at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:200) at scala.collection.immutable.List.flatMap(List.scala:45) at scala.tools.nsc.transform.SpecializeTypes.specializeClass(SpecializeTypes.scala:667) at scala.tools.nsc.transform.SpecializeTypes.transformInfo(SpecializeTypes.scala:1065) at scala.tools.nsc.transform.InfoTransform$Phase$$anon$1.transform(InfoTransform.scala:38) ..... ....
Using "var" without a re-declaration each time instead of val doesn't seem to help. How can I get the repl/sbt to free up / garbage collect the memory for that no-longer-relevant object reference?