从Map获取值时的Scala StackOverflowError

时间:2016-12-21 14:33:36

标签: scala stack-overflow scala-collections

经过一些重构后,我们突然发现这种情况在运行时发生:

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)

我们发现了类似的问题,但没有一个具有这种痕迹:

1 个答案:

答案 0 :(得分:4)

上述问题指出MapLike.mapValues的懒惰,经过一些进一步的研究,我们找到了原因。

我们有一些定期调用的清理代码,并执行以下操作:

  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")

解决方案是切换到Map.transform

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

或按照here

的说明强制观看视频
data.mapValues{ value =>
    value.filter(_._2.evictionTime.isBefore(Instant.now()))
}.view.force