Scala StackOverflowError when getting value from Map

309 Views Asked by At

After some refactoring we suddenly see this happening at runtime:

java.lang.StackOverflowError: null
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)

We found similar issues but none of them had exactly this trace:

1

There are 1 best solutions below

0
On BEST ANSWER

The mentioned issues point to the lazyness of MapLike.mapValues and after some further research we found the cause.

We have some cleanup code that is periodically called and does something like this:

  case class EvictableValue(value: String, evictionTime: Instant)

  val startData = Map(
    "node1" -> Map(
      "test" -> EvictableValue("bar",  Instant.now().plusSeconds(1000))
    )
  )

  // every n seconds we do the below code
  // here simulated by the fold
  val newData = (1 to 20000).foldLeft(startData){(data, _) =>
    data.mapValues { value =>
      value.filter(_._2.evictionTime.isBefore(Instant.now()))
    }
  }

  // this stack overflows
  val result = newData.get("test")

the solution was to switch to Map.transform

data.transform { (_, value) =>
    value.filter(_._2.evictionTime.isBefore(Instant.now()))
} 

or to force the view as explained here

data.mapValues{ value =>
    value.filter(_._2.evictionTime.isBefore(Instant.now()))
}.view.force