为什么sbt编译失败并出现StackOverflowError?

时间:2015-12-16 17:44:25

标签: scala sbt

我正在开发一个已经存在了几年的Scala项目,但对我来说还是新手。我的任务是将它从Scala 2.9.3升级到2.11.7及其依赖项。我已经过了错误和警告,但我无法让项目在SBT中成功编译。我总是在几乎相同的地方得到一个StackOverflowError。堆栈跟踪看起来像这样,但细节因Xss设置而异(目前为4M,但尝试高达24M):

java.lang.StackOverflowError
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:698)
at scala.tools.nsc.typechecker.Typers$Typer.runTyper$1(Typers.scala:5395)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedInternal(Typers.scala:5422)
at scala.tools.nsc.typechecker.Typers$Typer.body$2(Typers.scala:5369)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5373)
at scala.tools.nsc.typechecker.Typers$Typer.typedQualifier(Typers.scala:5471)
at scala.tools.nsc.typechecker.Typers$Typer.typedQualifier(Typers.scala:5479)
at scala.tools.nsc.transform.Erasure$Eraser.adaptMember(Erasure.scala:644)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:698)
at scala.tools.nsc.typechecker.Typers$Typer.runTyper$1(Typers.scala:5395)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedInternal(Typers.scala:5422)

SBT_OPTS看起来像这样:

-Xmx2G -Xss4M -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled

我可以在Intellij中成功“制作”项目,其他人可以从GitHub中取出我的更改并在sbt中编译项目,所以这个问题似乎是我的机器本地的问题(最新的四核Macbook Pro带有16GB RAM )。其他Scala / sbt项目在我的机器上成功编译。

以下是其他相关细节:

Scala version: 2.11.7
Java version: java version "1.8.0_66" (build 1.8.0_66-b17)
sbt version: 0.13.7 (have also tried 0.13.9)

我已经完全重建了ivy2缓存并清除了lib_managed目录。 scala-compiler.jar的版本与至少一台可以“成功编译”代码的机器上使用的版本相同。我做了一个干净的重新安装sbt(通过brew remove sbt,手动删除〜/ .sbt目录,然后brew install sbt)。

我没有尝试在发生错误时隔离正在编译的源代码行。我认为在某处查找配置问题或依赖性冲突会更有效率。

任何有关进一步故障排除的建议都将受到赞赏。

[已添加...]添加它作为实验,我从https://github.com/scala/scala下载了Scala语言源代码并尝试sbt compile时遇到以下非常类似的错误,这可能会有所帮助:

java.lang.StackOverflowError
at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.outerValue(ExplicitOuter.scala:229)
at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:441)
at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:352)
at scala.reflect.internal.Trees$class.itransform(Trees.scala:1345)
at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:44)
at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.scala$reflect$internal$Trees$UnderConstructionTransformer$$super$transform(ExplicitOuter.scala:219)
at scala.reflect.internal.Trees$UnderConstructionTransformer$class.transform(Trees.scala:1693)
at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:291)
at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:459)
at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:352)
at scala.reflect.internal.Trees$class.itransform(Trees.scala:1347)
at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)

这是有趣的事情。从this post开始,我发现了使用-d标志启动sbt以获取调试信息。得到以下输出:

Kevins-MacBook-Pro:scala kdoherty$ sbt -d
[process_args] java_version = '1.8.0_66'
# Executing command line:
java
-Xmx2G
-Xss4M
-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-Xmx384m
-Xss512k
-XX:+UseCompressedOops
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
-jar
/usr/local/Cellar/sbt/0.13.9/libexec/sbt-launch.jar

所以在某处我的SBT_OPTS设置被覆盖(默认情况下,我猜)。现在我需要找到这些默认值的来源。

8 个答案:

答案 0 :(得分:26)

我明白了。一旦我知道-d标志会告诉我SBT实际使用的是什么设置,我看到我的SBT_OPTS环境变量中的值被其他较低设置破坏了。那些人来自哪里?从我的JAVA_OPTS env变量!我应该早点注意到它们,但现在我知道我可以保留这些Java选项,并通过将特定于SBT的设置添加到我的/ usr / local / etc / sbtopts文件来覆盖它们

的格式有些尴尬
-J-Xmx2G
-J-Xss2M 

使用显示的值,我能够在我的项目上成功运行sbt compile

我希望有人觉得这很有用。

答案 1 :(得分:1)

我无法通过提供的答案使它起作用。 build.sbt设置和sbtopts文件都无法为我解决此错误。我要做的是使用sbt标志运行-mem,例如:

sbt -mem 2048 compile

,现在我的项目已经建立。如果使用IntelliJ,也可以转到

Preferences > Build, Execution, Deployment > Build Tools > sbt 

并将Maximum heap size, MB设置为所需的目标。

答案 2 :(得分:1)

我刚刚在Intellij sbt属性中添加了-Xss,问题已解决。

Intellij SBT properties

答案 3 :(得分:0)

我发现我的sbt install的bin / sbt文件中的SBT_OPT设置正在影响我的项目build.sbt中设置的内存值

将此文件中的现有-Xss值从1M更新为8M会将Scalac堆栈的内存大小提升到我在sbt调用的编译器中停止获取StackOverflow异常的程度。这看起来很奇怪,因为在编译器中设置堆栈大小的sbt记录方法是使用-J-Xss设置。

Sbt似乎并没有真正让你设置编译器的堆栈内存。虽然build.sbt接受以下配置作为有效设置,但它似乎不在编译器中应用该值:

ThisBuild中的scalacOptions ++ = Seq(-J-Xss8M)

我怀疑这是一个错误或未实现的功能

答案 4 :(得分:0)

添加到/ usr / local / etc / sbtopts的底部

-J-Xmx4G 
-J-Xss4M

所有设置。

答案 5 :(得分:0)

sbt -h输出中的相关部分:

  # jvm options and output control
  JAVA_OPTS          environment variable, if unset uses ""
  .jvmopts           if this file exists in the current directory, its contents
                     are appended to JAVA_OPTS
  SBT_OPTS           environment variable, if unset uses ""
  .sbtopts           if this file exists in the current directory, its contents
                     are prepended to the runner args

因此,就我而言,我通过创建包含内容的文件.sbtopts来解决了问题

-J-Xmx4G 
-J-Xss4M

在项目目录中。

注意:运行sbt -d显示已使用的设置,例如:

$ sbt -d
[addSbt] arg = '-debug'
[process_args] java_version = '8'
# Executing command line:
java
-Xms1024m
-XX:ReservedCodeCacheSize=128m
-XX:MaxMetaspaceSize=256m
-Xmx2G
-Xss2M
-jar
/path/to/sbt-launch.jar
-debug

答案 6 :(得分:0)

已经有多个正确答案。但是对我有用的是下面的

// Created and Added a File: .jvmopts in the Project Root Folder with below Parameters.
-Xms3022m
-Xmx4048m
-Xss124m
-XX:MaxPermSize=4048m
-XX:MaxMetaspaceSize=512m
-XX:+CMSClassUnloadingEnabled
-XX:ReservedCodeCacheSize=128m
-XX:MaxMetaspaceSize=256m

答案 7 :(得分:0)

最近我也遇到了这个问题,我发现了一个sbt 1.3.13可以解决此问题的解决方案。

  1. 在项目根目录下创建一个.sbtopts文件
  2. -J-Xss100M(或您认为合适的任何线程堆栈大小)添加到.sbtopts文件中