Як запобігти java.lang.OutOfMemoryError: простір PermGen при компіляції Scala?


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(еквівалентна проблема для Scala, що працює на Java 8), якщо замінити MaxPermSizeна MaxMetaspaceSize.
Brian McCutchon

Відповіді:


46

Причиною цього OutOfMemoryError: PermGen spaceє те, що йому не вистачає постійного простору для генерації :) Якщо ви використовуєте Oracle JVM, вам потрібно додати -XX:MaxPermSize=256Mаргумент (або інший обсяг місця) до вашого sbtсценарію. Для інших JVM перегляньте їх документацію.


1
Дякую Олексію. Я вже використовував опцію -Xmx512M. Я думаю, це повинно мати той самий ефект, так? Тим не менше я додав параметр -XX: MaxPermSize і перевірив, чи помилка не зникає.
BumbleGee

3
@BumbleGee Ні, пам’ять, додана користувачем, -Xmxне може використовуватися для PermGen.
Олексій Романов

Дякую за роз'яснення, Алекс.
BumbleGee

6
Це схоже на витік пам'яті в SBT, оскільки програма компілюється та успішно працює приблизно 3-5 разів, перш ніж видавати виняток, який виправлено перезапуском SBT.
Іван

4
Для поточної версії sbtвам потрібно -J-XX:MaxPermSize=256Mзамість -XX:MaxPermSize=256M. Відповідь Твароха є більш точною та повною, крім того, вона не висміює питання.
Даніель Дарабос

99

Я використовую HomeBrew для встановлення sbt на OS X. Він підтримує SBT_OPTSаргумент, який можна помістити у ~/.sbtconfigфайл export SBT_OPTS=-XX:MaxPermSize=256M.


1
Homebrew, здається, є дуже керованим пакетним рішенням при розробці з SBT. :)
crockpotveggies

скрипт встановлення sbt brew встановлює занадто малу пам’ять, позбудьтесь -Xmx512M у частині Java - cat which sbt#! / bin / sh test -f ~ / .sbtconfig && ~ / .sbtconfig exec java -Xmx512M $ {SBT_OPTS} -jar /usr/local/Cellar/sbt/0.13.1/libexec/sbt-launch.jar "$ @"
ski_squaw

є хороша настройка SBT_OPTS у scala-sbt.org/release/docs/Getting-Started/Setup.html
ski_squaw

працював у мене на Windows Set SBT_OPTS = -XX: MaxPermSize = 512M
Алекс Пуннен

Use of ~/.sbtconfig is deprecated, please migrate global settings to /usr/local/etc/sbtopts, Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256M; support was removed in 8.0
Нарфанатор

36

Я припустив, що ви використовуєте sbt 0.13.6 або вище. Створіть .sbtoptsфайл у корені вашого проекту sbt із таким вмістом:

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

MaxMetaspaceSizeце для Java 8, тоді MaxPermSizeяк для Java 7. Вони мають вирішальне значення для запобігання помилкам, пов’язаним із вичерпанням пермгену або метапростору . Звичайно, розгляньте можливість адаптації значень прапорів або додавання будь-яких інших потрібних прапорів.

Детальніше та альтернативні підходи можна знайти в цій публікації в блозі .


Чудово. Ви також можете помістити ці параметри у свій глобальний файл конфігурації; для мене це /usr/local/etc/sbtopts(для sbt, встановленого з Homebrew на Mac).
Брайан МакКутчон,

5

У мене була ця проблема, я погрався з нею протягом 10 хвилин, переглядаючи сайти, які намагаються змінити обсяг пам'яті.

Виявляється, я вирішив це,

user-profile$ sbt

Тоді,

sbt-project-name 0.1> clean

Це для мене це прояснило.


4

Для мене це виглядає як витік пам'яті в SBT, оскільки в моєму випадку програма компілюється та успішно працює приблизно 3-5 разів, перш ніж потрапити у виняток, який виправлено перезапуском SBT.

Справді, найбільш адекватним рішенням є -XX:MaxPermSize=параметр JVM, як пропонує Олексій Романов, або періодично перезапускати SBT, якщо це допомагає.

Але є ще один цікавий спосіб: спробуйте перейти на Java 8 . AFAIK більше не використовує PermGen і, мабуть, таким чином не застрахований від цього винятку.

Я все ще сподіваюся, що автори SBT розглянуть це питання в наступних версіях.


Отже, Java 8 використовує іншу систему пам’яті?
Адріан

У J8 генератор перманент просто перекидається в кучу пам’яті.
sksamuel

З Java 8 SBT не вдається скомпілювати, принаймні на моєму Mac. Мені потрібно перейти на Java 7.
Siyuan Ren

Можливо, ви робите щось не так, @CR Наскільки я пам'ятаю, я спробував це з Java 8 на Linux того часу (коли він був у глибокій бета-версії) без видимих ​​проблем, і зараз я використовую його з Java 8 у Windows. Можливо, ви могли б показати нам повідомлення про помилку компілятора, яке ви отримали?
Іван

Дякую за пропозицію допомогти, але я вирішив більше не йти через складний процес. Поки що я дотримуюся Java 7.
Siyuan Ren

2

Я будую з плагіном Jenkins sbt і мав ті самі проблеми. Вони були вирішені після копіювання SBT_OPTS із файлу sbt до прапорів 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"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.