Как предотвратить java.lang.OutOfMemoryError: PermGen space при компиляции 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.

Кто-нибудь знает, что может быть причиной этой ошибки? Заранее благодарим за понимание.

BumbleGee
источник
Ответы здесь также работают java.lang.OutOfMemoryError: Metaspace(эквивалентная проблема для Scala, работающего на Java 8), если вы замените их MaxPermSizeна MaxMetaspaceSize.
Брайан МакКатчон

Ответы:

46

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

Алексей Романов
источник
1
Спасибо, Алексей. Я уже использовал параметр -Xmx512M. Я думаю, это должно иметь такой же эффект, верно? Тем не менее я добавил параметр -XX: MaxPermSize и посмотрю, сохраняется ли ошибка.
BumbleGee
3
@BumbleGee Нет, добавленная память -Xmxне может использоваться для PermGen.
Алексей Романов
Спасибо за разъяснение, Алекс.
BumbleGee 01
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.

Michaelliu
источник
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
в scala-sbt.org/release/docs/Getting-Started/Setup.html есть хорошая настройка SBT_OPTS
ski_squaw,
работал у меня на Windows, установленном SBT_OPTS = -XX: MaxPermSize = 512M
Alex Punnen
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.
Сиюань Рен
Возможно, вы делаете что-то не так, @CR Насколько я помню, я пробовал это с Java 8 в Linux в то время (когда он был в глубокой бета-версии) без видимых проблем и сейчас использую его с Java 8 в Windows. Может быть, вы могли бы показать нам полученное вами сообщение об ошибке компилятора?
Иван
Спасибо за предложение помочь, но я решил больше не проходить через сложный процесс. Я пока буду придерживаться Java 7.
Сиюань Рен
2

Я строю с помощью плагина Jenkins sbt, и у меня были те же проблемы. Они были разрешены после копирования SBT_OPTS из файла sbt во флаги JVM конфигурации задания Jenkins.

Ниебо
источник
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"
КАРТИКЕЯН А.
источник