如何在Scala REPL中回收(垃圾回收)分配的内存?

3
我有一个程序,其中有一个大的不可变对象,在执行某个操作时返回一个修改过的版本。我尝试在sbt控制台中对其进行测试,类似于var myObj = getInitialObject();,然后反复调用myObj = myObj.getNewOne();。
旧对象没有任何引用,但内存似乎没有被释放。最终我收到了OutOfMemoryError: GC超时限制错误。我能够在scala repl提示符下使用一个简单的示例重现这个问题。
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,.... (省略其余输出) scala> val foo = List.fill(1000000) { new Object() } .... 再重复几次,最后得到:
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) ..... ....

每次使用"var"而不是val进行重新声明似乎并没有帮助。我该如何让repl/sbt释放这个不再相关的对象引用的内存/垃圾收集呢?


1
你总是从解释器中运行吗?我猜测解释器本身正在持有一个引用。命令行Scala解释器会保留这些引用,以便您可以进行反向引用。在确保已经释放引用的真正编译程序中尝试一下。 - Tony K.
1
是的,我正在解释器中运行这个程序。关键是我想能够从解释器中测试我的应用程序,而不会因为内存不足而停止...这样测试更容易。 - nairbv
网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接