Является ли java.lang.OutOfMemoryError: нормальный метапас в sbt REPL?

Я новичок в Scala, sbt и REPL. Единственное, что мне очень нравится, это опция ~ для циклического запуска или компиляции при редактировании файлов. Поэтому я часто запускаю ~run.

Но он теряет память. Поскольку после 20-30 запусков вся интерактивная оболочка sbt вылетает с:

[info] Compiling 1 Scala source to /home/[redacted]
sbt appears to be exiting abnormally.
The log file for this session is at /tmp/sbt853875123365456892.log
java.lang.OutOfMemoryError: Metaspace
Error during sbt execution: java.lang.OutOfMemoryError: Metaspace

Честно говоря, это неважно, но пока я понимаю, что такое OOME, вопрос, который я пытаюсь выяснить, действительно ли это так? Ответ "нет", но...

  • Это ошибка sbt? (должен ли я попытаться сообщить об этом?)
  • Что-то не так с моей программой? (утечка памяти?)

Ответ 1

В основном SBT, когда компилирует и запускает вашу программу, использует только одну JVM - ту, с которой она была запущена. Таким образом, если в метапассе есть что-то, что не может быть собрано в мусор, у вас может не хватить памяти - например, если вы создаете какое-либо соединение (я видел примеры MongoDB или ElasticSearch) и забыл закрыть его при выключении, он останется открытым, предотвращая вы собираете несколько объектов - после нескольких циклов перекомпиляции-перезагрузки эти несколько объектов могут использовать ваш метапас.

Таким образом, это утечка памяти, которая обычно не влияет на вашу программу, но SBT делает ее видимой как исключение, которое вы видели.

В долгосрочной перспективе вы должны идентифицировать утечку и удалить ее, для обходного пути вы можете использовать что-то вроде револьвера SBT, что позволяет вам запускать программу в другой JVM - таким образом, утечки памяти не будут суммироваться, так как вы будете просто закрывать и запускать новую JVM вместо того, чтобы запускать все в одной JVM как SBT.