Jak zapobiec java.lang.OutOfMemoryError: PermGen space w kompilacji Scala?

79

Zauważyłem dziwne zachowanie mojego kompilatora Scala. Czasami podczas kompilowania klasy zgłasza OutOfMemoryError. Oto komunikat o błędzie:

[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

Dzieje się to tylko raz na jakiś czas, a błąd zwykle nie jest zgłaszany przy kolejnym uruchomieniu kompilacji. Używam Scali 2.9.0 i kompiluję przez SBT.

Czy ktoś ma wskazówkę, co może być przyczyną tego błędu? Z góry dziękuję za spostrzeżenia.

BumbleGee
źródło
Odpowiedzi tu również pracować java.lang.OutOfMemoryError: Metaspace(odpowiednik problem dla Scala działa na Java 8), jeśli zastąpi MaxPermSizesię MaxMetaspaceSize.
Brian McCutchon

Odpowiedzi:

46

Przyczyną OutOfMemoryError: PermGen spacejest to, że nie ma wystarczająco dużo miejsca na generowanie. Jeśli używasz Oracle JVM, musisz dodać -XX:MaxPermSize=256Margument (lub inną ilość miejsca) do swojego sbtskryptu. W przypadku innych maszyn JVM zajrzyj do ich dokumentacji.

Alexey Romanov
źródło
1
Dzięki Alexey. Użyłem już opcji -Xmx512M. Myślę, że to powinno mieć taki sam efekt, prawda? Mimo to dodałem parametr -XX: MaxPermSize i zobaczę, czy błąd nadal występuje.
BumbleGee
3
@BumbleGee Nie, pamięć dodana przez -Xmxnie może być używana dla PermGen.
Alexey Romanov
Dzięki za wyjaśnienie, Alex.
BumbleGee
6
Wygląda to na wyciek pamięci w SBT, gdy program kompiluje się i działa z powodzeniem około 3-5 razy, zanim zgłosi wyjątek, który jest naprawiany przez ponowne uruchomienie SBT.
Ivan
4
W obecnej wersji sbtpotrzebujesz -J-XX:MaxPermSize=256Mzamiast -XX:MaxPermSize=256M. Odpowiedź Tvaroha jest dokładniejsza i bardziej kompletna, a ponadto nie wyśmiewa pytania.
Daniel Darabos,
99

Używam HomeBrew do instalacji sbt na OS X. Obsługuje SBT_OPTSargument, który można wstawić do ~/.sbtconfigplikuexport SBT_OPTS=-XX:MaxPermSize=256M .

michaelliu
źródło
1
Homebrew wydaje się być bardzo łatwym w zarządzaniu rozwiązaniem pakietowym podczas programowania z SBT. :)
crockpotveggies
skrypt instalacyjny sbt brew ustawia pamięć max na zbyt małą, pozbądź się -Xmx512M w części 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
jest dobre ustawienie SBT_OPTS w scala-sbt.org/release/docs/Getting-Started/Setup.html
ski_squaw Kwietnia
pracował dla mnie na zestaw 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
Narfanator
36

Zakładam, że używasz sbt 0.13.6 lub nowszego. Utwórz .sbtoptsplik w katalogu głównym swojego projektu SBT z następującą zawartością:

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

MaxMetaspaceSizejest dla Javy 8, a MaxPermSizedla Javy 7. Są one krytyczne dla zapobiegania błędom braku pamięci związanym z permgen lub metaspace wyczerpaniem . Oczywiście rozważ dostosowanie wartości flag lub dodanie innych wymaganych flag.

Więcej szczegółów i alternatywnych podejść można znaleźć w tym poście na blogu .

Tvaroh
źródło
Świetny. Możesz również umieścić te opcje w swoim globalnym pliku konfiguracyjnym; dla mnie to /usr/local/etc/sbtopts(dla sbt zainstalowanego z Homebrew na Macu).
Brian McCutchon
5

Miałem ten problem, bawiłem się nim przez 10 minut, patrząc na strony próbujące zmienić rozmiar pamięci.

Okazuje się, że rozwiązałem to przez

user-profile$ sbt

Następnie,

sbt-project-name 0.1> clean

To wyjaśniło mi to.

Alex Stewart
źródło
4

Wygląda to na wyciek pamięci w SBT, ponieważ w moim przypadku program kompiluje się i działa z powodzeniem około 3-5 razy, zanim trafi w wyjątek, który jest naprawiany przez restart SBT.

Wydaje się, że najbardziej odpowiednim rozwiązaniem wydaje się być -XX:MaxPermSize=parametr JVM, jak sugeruje Alexey Romanov, lub okresowe ponowne uruchamianie SBT, jeśli to pomaga.

Ale jest inny interesujący sposób: spróbuj przejść na Javę 8 . AFAIK nie używa już PermGen i prawdopodobnie jest w ten sposób odporny na ten wyjątek.

Nadal mam nadzieję, że autorzy SBT zajmą się tym problemem w przyszłych wersjach.

Ivan
źródło
Więc Java 8 używa innego systemu pamięci?
Adrian
W J8 gen perm jest po prostu wprowadzany do przestrzeni sterty pamięci.
sksamuel
Z Java 8 SBT nie kompiluje się, przynajmniej na moim Macu. Muszę przejść na wersję Java 7.
Siyuan Ren
Być może robisz coś nie tak, @CR O ile pamiętam, wypróbowałem ją wtedy z Javą 8 na Linuksie (kiedy była w głębokiej wersji beta) bez widocznych problemów i używam jej teraz z Javą 8 na Windowsie. Może mógłbyś pokazać nam komunikat o błędzie kompilatora, który otrzymałeś?
Ivan
Dziękuję za propozycję pomocy, ale postanowiłem nie przechodzić ponownie przez ten skomplikowany proces. Na razie pozostanę przy Javie 7.
Siyuan Ren
2

Buduję za pomocą wtyczki Jenkins sbt i miałem te same problemy. Zostały rozwiązane po skopiowaniu SBT_OPTS z pliku sbt do flag JVM konfiguracji zadania Jenkinsa.

niebo
źródło
2

Pierwotnie przy użyciu polecenia takiego jak:

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

Dostałem najpierw przestrzeń OutOfMemoryError: PermGen, którą rozwiązałem za pomocą -XX:MaxPermSize, a następnie OutOfMemoryError: przestrzeń sterty Java , na którą -Xmxbyło lekarstwem.

Więc w moim przypadku takie polecenie zadziałało:

java -XX:MaxPermSize=256M -Xmx2048M -jar /path/to/sbt-launch.jar test
Jonik
źródło
0

zmień następujący blok kodu w pliku sbt.sh i zapisz jego działanie.

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"
}

lub

za pomocą terminala do eksportu sbt config

export SBT_OPTS="-XX:+CMSClassUnloadingEnabled -XX:PermSize=1024M -XX:MaxPermSize=2048M"
KARTHIKEYAN.A
źródło