Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala.tools.nsc.interpreter memory leak

I need to implement a DSL (Domain Specific Language) using Scala, and this DSL will be interpreted in a Scala interpreter (scala.tools.nsc.interpreter). The problem is that the memory used by the interpreter keeps increasing until an outOfMemory exception is thrown. I cannot reinitialize the interpreter each time I have a line of DSL to execute, as the interpreter takes a while to load. I cannot just call reset(), as I need to keep track of some data in the execution environment of the interpreter.

Memory leak will happen even I do the following:

while (true)
{
 interpreter.interpret("println(4 + 5)")
}

After a while, I'll get:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at ch.epfl.lamp.util.ByteArray.<init>(ByteArray.java:24)
    at ch.epfl.lamp.fjbg.JCode.<init>(JCode.java:47)
    at ch.epfl.lamp.fjbg.JExtendedCode.<init>(JExtendedCode.java:113)
    at ch.epfl.lamp.fjbg.FJBGContext.JCode(FJBGContext.java:122)
    at ch.epfl.lamp.fjbg.JMethod.<init>(JMethod.java:52)
    at ch.epfl.lamp.fjbg.FJBGContext.JMethod(FJBGContext.java:87)
    at ch.epfl.lamp.fjbg.JClass.addNewMethod(JClass.java:246)
    at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.genMethod(GenJVM.scala:755)
    at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator$$anonfun$genClass$7.apply(GenJVM.scala:307)
    at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator$$anonfun$genClass$7.apply(GenJVM.scala:307)
    at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
    at scala.collection.immutable.List.foreach(List.scala:45)
    at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.genClass(GenJVM.scala:307)
    at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase$$anonfun$run$4.apply(GenJVM.scala:86)
    at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase$$anonfun$run$4.apply(GenJVM.scala:86)
    at scala.collection.mutable.HashMap$$anon$2$$anonfun$foreach$3.apply(HashMap.scala:102)
    at scala.collection.mutable.HashMap$$anon$2$$anonfun$foreach$3.apply(HashMap.scala:102)
    at scala.collection.Iterator$class.foreach(Iterator.scala:660)
    at scala.collection.mutable.HashTable$$anon$1.foreach(HashTable.scala:157)
    at scala.collection.mutable.HashTable$class.foreachEntry(HashTable.scala:190)
    at scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:43)
    at scala.collection.mutable.HashMap$$anon$2.foreach(HashMap.scala:102)
    at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase.run(GenJVM.scala:86)
    at scala.tools.nsc.Global$Run.compileSources(Global.scala:953)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.compileAndSaveRun(IMain.scala:756)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.compile(IMain.scala:731)
    at scala.tools.nsc.interpreter.IMain$Request.compile(IMain.scala:873)
    at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:576)
    at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:543)
    at com.ericsson.ims_dsl.IMS_Interpreter$$anonfun$e$1.apply(IMS_Interpreter.scala:50)
    at com.ericsson.ims_dsl.IMS_Interpreter$$anonfun$e$1.apply(IMS_Interpreter.scala:50)
    at scala.tools.nsc.interpreter.IMain.beQuietDuring(IMain.scala:200)

Could someone please help me solve this issue?

like image 333
Peter Avatar asked Sep 28 '11 16:09

Peter


1 Answers

Every time you call the interpret method, the request is stored. Therefore if you try to call an infinite number of time this method, you should run into trouble. So it's not really a bug.

You can increase the number of possible iterations before crash by increasing the JVM maximum heap size... You may want to count the number of possible calls to check if it meets your goal.

like image 135
paradigmatic Avatar answered Oct 16 '22 08:10

paradigmatic