如何避免 java.lang.OutOfMemoryError: PermGen space 错误?

35

我经常从SBT收到OutOfMemoryError错误。

> test
[error] java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
[error] Use 'last' for the full log.
> last
[debug] Running task... Cancelable: false, check cycles: false
[debug]
[debug] Initial source changes:
[debug]     removed:Set()
[debug]     added: Set()
[debug]     modified: Set()
[debug] Removed products: Set()
[debug] Modified external sources: Set()
[debug] Modified binary dependencies: Set()
[debug] Initial directly invalidated sources: Set()
[debug]
[debug] Sources indirectly invalidated by:
[debug]     product: Set()
[debug]     binary dep: Set()
[debug]     external source: Set()
[debug] Initially invalidated: Set()
[debug] Copy resource mappings:
[debug]
[debug]
[debug] Initial source changes:
[debug]     removed:Set()
[debug]     added: Set()
[debug]     modified: Set()
[debug] Removed products: Set()
[debug] Modified external sources: Set()
[debug] Modified binary dependencies: Set()
[debug] Initial directly invalidated sources: Set()
[debug]
[debug] Sources indirectly invalidated by:
[debug]     product: Set()
[debug]     binary dep: Set()
[debug]     external source: Set()
[debug] Initially invalidated: Set()
[debug] Copy resource mappings:
[debug]
[debug] Framework implementation 'org.scalacheck.ScalaCheckFramework' not present.
[debug] Framework implementation 'org.specs.runner.SpecsFramework' not present.
[debug] Framework implementation 'org.scalatest.tools.ScalaTestFramework' not present.
[debug] Framework implementation 'com.novocode.junit.JUnitFramework' not present.
[debug] Subclass fingerprints: Stream((org.specs2.specification.SpecificationStructure,false,org.specs2.runner.Fingerprints$$anon$1@34d6488c), ?)
[debug] Annotation fingerprints: Stream()
[debug] Running Test ExpandoObjectTest : subclass(false, org.specs2.specification.SpecificationStructure) with arguments
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
    at java.util.concurrent.FutureTask.get(FutureTask.java:111)
    at sbt.ConcurrentRestrictions$$anon$4.take(ConcurrentRestrictions.scala:196)
    at sbt.Execute.next$1(Execute.scala:85)
    at sbt.Execute.processAll(Execute.scala:88)
    at sbt.Execute.runKeep(Execute.scala:68)
    at sbt.EvaluateTask$.run$1(EvaluateTask.scala:162)
    at sbt.EvaluateTask$.runTask(EvaluateTask.scala:177)
    at sbt.Aggregation$$anonfun$4.apply(Aggregation.scala:46)
    at sbt.Aggregation$$anonfun$4.apply(Aggregation.scala:44)
    at sbt.EvaluateTask$.withStreams(EvaluateTask.scala:137)
    at sbt.Aggregation$.runTasksWithResult(Aggregation.scala:44)
    at sbt.Aggregation$.runTasks(Aggregation.scala:59)
    at sbt.Aggregation$$anonfun$applyTasks$1.apply(Aggregation.scala:31)
    at sbt.Aggregation$$anonfun$applyTasks$1.apply(Aggregation.scala:30)
    at sbt.Command$$anonfun$applyEffect$2$$anonfun$apply$3.apply(Command.scala:62)
    at sbt.Command$$anonfun$applyEffect$2$$anonfun$apply$3.apply(Command.scala:62)
    at sbt.Command$.process(Command.scala:90)
    at sbt.MainLoop$$anonfun$next$1$$anonfun$apply$1.apply(MainLoop.scala:71)
    at sbt.MainLoop$$anonfun$next$1$$anonfun$apply$1.apply(MainLoop.scala:71)
    at sbt.State$$anon$2.process(State.scala:170)
    at sbt.MainLoop$$anonfun$next$1.apply(MainLoop.scala:71)
    at sbt.MainLoop$$anonfun$next$1.apply(MainLoop.scala:71)
    at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
    at sbt.MainLoop$.next(MainLoop.scala:71)
    at sbt.MainLoop$.run(MainLoop.scala:64)
    at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:53)
    at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:50)
    at sbt.Using.apply(Using.scala:25)
    at sbt.MainLoop$.runWithNewLog(MainLoop.scala:50)
    at sbt.MainLoop$.runAndClearLast(MainLoop.scala:33)
    at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:17)
    at sbt.MainLoop$.runLogged(MainLoop.scala:13)
    at sbt.xMain.run(Main.scala:26)
    at xsbt.boot.Launch$.run(Launch.scala:55)
    at xsbt.boot.Launch$$anonfun$explicit$1.apply(Launch.scala:45)
    at xsbt.boot.Launch$.launch(Launch.scala:69)
    at xsbt.boot.Launch$.apply(Launch.scala:16)
    at xsbt.boot.Boot$.runImpl(Boot.scala:31)
    at xsbt.boot.Boot$.main(Boot.scala:20)
    at xsbt.boot.Boot.main(Boot.scala)
Caused by: java.lang.OutOfMemoryError: PermGen space
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at sbt.Project$$anon$5.apply(Project.scala:130)
    at sbt.Project$$anon$5.apply(Project.scala:128)
    at sbt.LogManager$.commandBase$1(LogManager.scala:59)
    at sbt.LogManager$.command$1(LogManager.scala:60)
    at sbt.LogManager$$anonfun$suppressedMessage$1.apply(LogManager.scala:61)
    at sbt.LogManager$$anonfun$suppressedMessage$1.apply(LogManager.scala:61)
    at sbt.ConsoleLogger.trace(ConsoleLogger.scala:163)
    at sbt.AbstractLogger.log(Logger.scala:32)
    at sbt.MultiLogger$$anonfun$dispatch$1.apply(MultiLogger.scala:40)
    at sbt.MultiLogger$$anonfun$dispatch$1.apply(MultiLogger.scala:38)
    at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
    at scala.collection.immutable.List.foreach(List.scala:76)
    at sbt.MultiLogger.dispatch(MultiLogger.scala:38)
    at sbt.MultiLogger.trace(MultiLogger.scala:30)
    at sbt.TestLogger$$anon$2.trace(TestReportListener.scala:71)
    at sbt.TestLogger.endGroup(TestReportListener.scala:88)
    at sbt.TestRunner$$anonfun$run$5.apply(TestFramework.scala:87)
    at sbt.TestRunner$$anonfun$run$5.apply(TestFramework.scala:87)
    at sbt.TestFramework$$anonfun$safeForeach$1.apply(TestFramework.scala:112)
    at sbt.TestFramework$$anonfun$safeForeach$1.apply(TestFramework.scala:112)
    at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
[error] java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
[error] Use 'last' for the full log.

有时候,它也会突然退出,并显示以下内容:
sbt appears to be exiting abnormally.
  The log file for this session is at /var/folders/vf/3khb58091wd0_1rz1yh6knb00000gp/T/sbt3242766352271599341.log
java.lang.OutOfMemoryError: PermGen space
Error during sbt execution: java.lang.OutOfMemoryError: PermGen space

有什么解决方案吗?


你没有说明使用的是哪个版本的SBT,但早期版本在重新加载项目定义几次后很容易耗尽PermGen。目前的版本似乎相对免疫这个问题,但你可能仍然需要增加分配量。 - Randall Schulz
@RandallSchulz,版本号是0.12.2。 - missingfaktor
请提供Java版本和操作系统信息。 - appbootup
@SSR,1.7.0_10和OS X Mountain Lion。 - missingfaktor
查看此解决方案:https://dev59.com/F2sy5IYBdhLWcg3wxQ0j#29318498。 - Tvaroh
1个回答

52
有时在编译大型代码库时会出现这种情况——许多类被加载到运行sbt的VM中。您需要增加sbt的PermGen空间——使用标志-XX:MaxPermSize=256m,其中256可以更改为所需永久代的大小。运行:
cat `which sbt`

要找到你的sbt启动脚本。然后编辑它,以包含使用类似于这里描述的修改-Xmx-Xms的方式运行sbt启动器的java命令标志。

添加-XX:+CMSClassUnloadingEnabled标志也应该使sbt能够卸载不再使用的先前编译运行中的类加载器中的类。

编辑:

或者,如果您正在使用扩展脚本运行sbt,则可以在SBT_OPTS环境变量中设置这些选项。


你能否也使用 SBT_OPTS 环境变量来设置它? - HeatfanJohn
我相信这取决于你使用的SBT运行脚本 - 如果你使用这个运行SBT的扩展脚本,它应该会捕捉到SBT_OPTS变量设置并允许做更多事情:https://github.com/paulp/sbt-extras/blob/master/sbt - axel22
这似乎对某些人不起作用,他们必须使用SBT_OPTS。请您编辑您的答案以提及此事,这给我的同事带来了很多痛苦。(然后我会点赞 :)) - samthebest
3
谢谢,这很有帮助。由于在OSX上使用brew安装时,sbt的默认最大内存设置太小了,因此Typesafe activator无法正常工作。我编辑了与SBA_OPTS相关联的脚本,该脚本位于Cellar中,详细信息请参考上述链接。现在一切都运行良好。 - ski_squaw
在Manjaro Linux中,sbt脚本位于/usr/bin/sbt,我将该行配置如下:java $SBT_OPTS -XX:MaxPermSize=1200m -jar /usr/share/java/sbt/sbt-launch.jar "$@"。 - punkdata

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接