Scala 意外的堆栈溢出
我用Scala编写了这个基本程序:Scala 意外的堆栈溢出,scala,stack-overflow,Scala,Stack Overflow,我用Scala编写了这个基本程序: import scala.collection.mutable.HashMap object HelloWorld { val treasureMap = new HashMap[BigInt, BigInt] def main(args: Array[String]) { println(fibCache(10)) } def fibCache(n: BigInt): BigInt = { if (n == 0 ||
import scala.collection.mutable.HashMap
object HelloWorld {
val treasureMap = new HashMap[BigInt, BigInt]
def main(args: Array[String]) {
println(fibCache(10))
}
def fibCache(n: BigInt): BigInt = {
if (n == 0 || n == 1) {
return n
}
return treasureMap.getOrElseUpdate(n, fibCache(n - 1) + fibCache(n - 2))
}
}
我希望对于非常大的值,我会有OutOfMemoryError或其他什么,但我看到的是:
Exception in thread "main" java.lang.StackOverflowError
at java.math.BigInteger.compareMagnitude(Unknown Source)
at java.math.BigInteger.compareTo(Unknown Source)
at scala.math.BigInt.compare(BigInt.scala:141)
at scala.math.BigInt.$less$eq(BigInt.scala:145)
at scala.math.BigInt.fitsInLong(BigInt.scala:130)
at scala.math.BigInt.hashCode(BigInt.scala:120)
at scala.runtime.BoxesRunTime.hashFromNumber(Unknown Source)
at scala.collection.mutable.HashTable$HashUtils$class.elemHashCode(HashTable.scala:366)
at scala.collection.mutable.HashMap.elemHashCode(HashMap.scala:43)
at scala.collection.mutable.HashTable$class.findEntry(HashTable.scala:108)
at scala.collection.mutable.HashMap.findEntry(HashMap.scala:43)
at scala.collection.mutable.HashMap.get(HashMap.scala:63)
at scala.collection.mutable.MapLike$class.getOrElseUpdate(MapLike.scala:186)
at scala.collection.mutable.HashMap.getOrElseUpdate(HashMap.scala:43)
有人能解释一下原因吗?还有,我是否可以使用运行时设置来缓解这种情况?-Xss会有帮助吗?StackOverflower错误是关于内存耗尽主题的一个变体,它只是精确地说明哪个内存区域已经耗尽 所以,是的,
-Xss
会有所帮助,但有更好的方法
此页面有几个可供选择的实现,您可以尝试:
您需要使用尾部递归或基于流的变体来降低堆栈大小。刚刚在我的机器(3GB Macbook)上用最新版本的scala运行了它,它按预期运行。您使用了多大的值?结果是什么?32/64位、可用物理内存和-Xss参数都会影响问题发生的确切点,因此不要担心实际选择的数字。根据您的配置,知道这会在某个时候爆发就足够了。我很熟悉StackOverflow是什么。当我用Java编写这个等价物时,情况并非如此。在清理堆栈之前,它会耗尽内存。@阿米尔Scala发出的代码倾向于比Java代码更依赖于堆栈。特别是如果您是以更具功能性的风格编写,或者通过使用包装Java标准库中的方法的Scala方法向堆栈添加两个级别。我不会让你担心的,我明白了。谢谢你的评论。尾部递归实现是如何保持堆栈大小的?基于jvm的语言(如scala、clojure)不进行尾部调用优化,因为jvm不支持它。@Babu jvm不进行尾部调用优化。斯卡拉有。