Scala编译时如何防止java.lang.OutOfMemoryError:PermGen空间?


79

我注意到我的Scala编译器有一个奇怪的行为。编译类时,有时会抛出OutOfMemoryError。这是错误消息:

[info] Compiling 1 Scala source to /Users/gruetter/Workspaces/scala/helloscala/target/scala-2.9.0/test-classes...
java.lang.OutOfMemoryError: PermGen space
Error during sbt execution: java.lang.OutOfMemoryError: PermGen space

它只会偶尔发生一次,并且通常不会在随后的编译运行中引发该错误。我使用Scala 2.9.0并通过SBT进行编译。

是否有人知道导致此错误的原因?预先感谢您的见解。


java.lang.OutOfMemoryError: Metaspace如果将替换为MaxPermSize,那么这里的答案也适用于(在Java 8上运行的Scala等效问题)MaxMetaspaceSize
Brian McCutchon

Answers:


46

原因OutOfMemoryError: PermGen space是它没有足够的永久生成空间:)如果使用的是Oracle JVM,则需要-XX:MaxPermSize=256Msbt脚本中添加(或其他一些空间)参数。对于其他JVM,请查看其文档。


1
谢谢阿列克谢。我已经使用了-Xmx512M选项。我认为应该具有相同的效果,对吗?尽管如此,我还是添加了-XX:MaxPermSize参数,并查看错误是否仍然存在。
BumbleGee

3
@BumbleGee不,添加的内存-Xmx不能用于PermGen。
阿列克谢·罗曼诺夫

感谢您的澄清,Alex。
BumbleGee 2011年

6
看起来像SBT中的内存泄漏,因为程序会编译并成功运行约3-5次,然后抛出由SBT重新启动修复的异常。
伊万

4
对于当前版本,sbt您需要-J-XX:MaxPermSize=256M而不是-XX:MaxPermSize=256M。Tvaroh的答案更加准确和完整,而且没有使这个问题变得有趣。
Daniel Darabos

99

我使用HomeBrew在OS X上安装sbt。它支持SBT_OPTS可以用放置在~/.sbtconfig文件中的参数export SBT_OPTS=-XX:MaxPermSize=256M


1
使用SBT开发时,Homebrew似乎是一个非常易于管理的软件包解决方案。:)
crockpotveggies

sbt brew install脚本将内存最大值设置得太小,摆脱Java部分-cat which sbt#!/ bin / sh test -f〜/ .sbtconfig &&中的-Xmx512M。〜/ .sbtconfig执行java -Xmx512M $ {SBT_OPTS} -jar /usr/local/Cellar/sbt/0.13.1/libexec/sbt-launch.jar“ $ @”
ski_squaw


在Windows set SBT_OPTS = -XX:MaxPermSize = 512M上为我工作
Alex Punnen

Use of ~/.sbtconfig is deprecated, please migrate global settings to /usr/local/etc/sbtoptsJava HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256M; support was removed in 8.0
Narfanator

36

我假设您使用的是sbt 0.13.6或更高版本。.sbtoptssbt项目的根目录中创建文件,其内容如下:

-J-Xmx4G
-J-XX:MaxMetaspaceSize=1G
-J-XX:MaxPermSize=1G
-J-XX:+CMSClassUnloadingEnabled

MaxMetaspaceSize是针对Java 8的,而MaxPermSize针对Java 7的。它们对于防止与permgen或元空间耗尽有关的内存不足错误至关重要。当然,请考虑调整标志值或添加所需的任何其他标志。

可以在此博客文章中找到更多详细信息和替代方法。


大。您也可以将这些选项放在全局配置文件中。对我来说/usr/local/etc/sbtopts(对于Mac上随Homebrew一起安装的sbt)。
Brian McCutchon

5

我遇到了这个问题,在尝试更改内存大小的站点上玩了10分钟。

原来我解决了,

user-profile$ sbt

然后,

sbt-project-name 0.1> clean

这为我清除了。


4

对我来说,这似乎是SBT中的内存泄漏,因为在我的情况下,程序编译并成功运行了3-5次,然后才遇到SBT重新启动所修复的异常。

实际上,最合适的解决方案似乎是-XX:MaxPermSize=Alexey Romanov建议的JVM参数,或者如果有帮助,则定期重新启动SBT。

但是还有另一种有趣的方式:尝试切换到Java 8。据我所知,它不再使用PermGen,并且可能不受这种异常的影响。

我仍然希望SBT作者能够在将来的版本中解决此问题。


Java 8是否使用其他内存系统?
阿德里安

在J8中,将perm gen滚动到内存堆空间中。
sksamuel

使用Java 8,SBT至少在我的Mac上无法编译。我不得不降级到Java 7
思源仁

@CR也许您做错了,据我所记得,我当时曾在Linux 8上的Java 8上进行过尝试(当时它处于beta版),没有明显的问题,现在正在Windows 8上使用Java 8。也许您可以向我们展示您收到的编译器错误消息?
伊万

感谢您提供帮助,但是我决定不再进行复杂的过程。我暂时会坚持使用Java 7。
思源仁

2

我正在使用Jenkins sbt插件进行构建,并且遇到了同样的问题。将SBT_OPTS从sbt文件复制到Jenkins作业配置的JVM标志后,这些问题已解决。


2

最初使用如下命令:

java -jar /path/to/sbt-launch.jar test

我得到了第一的OutOfMemoryError:PermGen的空间,这是我使用解决了-XX:MaxPermSize,然后的OutOfMemoryError:Java堆空间,到-Xmx了补救措施。

因此,就我而言,这样的命令有效:

java -XX:MaxPermSize=256M -Xmx2048M -jar /path/to/sbt-launch.jar test

0

更改sbt.sh文件中的以下代码块并保存其正常工作。

get_mem_opts () {
  local mem=${1:-1536}
  local perm=$(( $mem / 4 ))
  (( $perm > 256 )) || perm=1024 //256 to 1024
  (( $perm < 1024 )) || perm=2048 // 1024 to 2048
  local codecache=$(( $perm / 2 ))

  echo "-Xms${mem}m -Xmx${mem}m -XX:MaxPermSize=${perm}m -XX:ReservedCodeCacheSize=${codecache}m"
}

要么

使用终端导出sbt配置

export SBT_OPTS="-XX:+CMSClassUnloadingEnabled -XX:PermSize=1024M -XX:MaxPermSize=2048M"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.