So verhindern Sie java.lang.OutOfMemoryError: PermGen-Speicherplatz bei der Scala-Kompilierung?

79

Ich habe ein seltsames Verhalten meines Scala-Compilers bemerkt. Beim Kompilieren einer Klasse wird gelegentlich ein OutOfMemoryError ausgelöst. Hier ist die Fehlermeldung:

[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

Es kommt nur gelegentlich vor und der Fehler wird normalerweise beim nachfolgenden Kompilierungslauf nicht ausgelöst. Ich benutze Scala 2.9.0 und kompiliere über SBT.

Hat jemand eine Ahnung, was die Ursache für diesen Fehler sein könnte? Vielen Dank im Voraus für Ihre Erkenntnisse.

BumbleGee
quelle
Die Antworten hier auch arbeiten java.lang.OutOfMemoryError: Metaspace(das Äquivalent Problem für Scala läuft auf Java 8) , wenn Sie ersetzen MaxPermSizemit MaxMetaspaceSize.
Brian McCutchon

Antworten:

46

Die Ursache dafür OutOfMemoryError: PermGen spaceist, dass nicht genügend permanenter Generierungsspeicher vorhanden ist :) Wenn Sie Oracle JVM verwenden, müssen Sie -XX:MaxPermSize=256MIhrem sbtSkript das Argument (oder eine andere Menge an Speicherplatz) hinzufügen . Weitere JVMs finden Sie in deren Dokumentation.

Alexey Romanov
quelle
1
Danke Alexey. Ich habe bereits die Option -Xmx512M verwendet. Ich denke, das sollte den gleichen Effekt haben, oder? Ich habe trotzdem den Parameter -XX: MaxPermSize hinzugefügt und geprüft, ob der Fehler weiterhin besteht.
BumbleGee
3
@BumbleGee Nein, der von hinzugefügte Speicher -Xmxkann nicht für PermGen verwendet werden.
Alexey Romanov
Danke, dass du das klargestellt hast, Alex.
BumbleGee
6
Es sieht aus wie ein Speicherverlust in SBT, wenn das Programm etwa 3-5 Mal kompiliert und erfolgreich ausgeführt wird, bevor die Ausnahme ausgelöst wird, die durch den SBT-Neustart behoben wird.
Ivan
4
Für die aktuelle Version sbtbenötigen Sie -J-XX:MaxPermSize=256Mstatt -XX:MaxPermSize=256M. Tvarohs Antwort ist genauer und vollständiger und macht sich über die Frage nicht lustig.
Daniel Darabos
99

Ich verwende HomeBrew, um sbt unter OS X zu installieren. Es unterstützt ein SBT_OPTSArgument, mit dem eine ~/.sbtconfigDatei erstellt werden kann export SBT_OPTS=-XX:MaxPermSize=256M.

michaelliu
quelle
1
Homebrew scheint bei der Entwicklung mit SBT eine sehr überschaubare Paketlösung zu sein. :)
Crockpotveggies
Das sbt Brew-Installationsskript setzt den maximalen Speicher zu klein. Entfernen Sie das -Xmx512M im Java-Teil - 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
Es gibt eine gute SBT_OPTS-Einstellung in scala-sbt.org/release/docs/Getting-Started/Setup.html
Ski_squaw
arbeitete für mich unter Windows Set 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

Ich nahm an, dass Sie sbt 0.13.6 oder höher verwenden. Erstellen Sie eine .sbtoptsDatei im Stammverzeichnis Ihres sbt- Projekts mit folgendem Inhalt:

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

MaxMetaspaceSizeist für Java 8, während MaxPermSizees für Java 7 ist. Sie sind wichtig , um Speicherfehler zu vermeiden, die entweder auf Permgen- oder Metaspace- Erschöpfung zurückzuführen sind. Erwägen Sie natürlich, die Flag-Werte anzupassen oder andere erforderliche Flags hinzuzufügen.

Weitere Details und alternative Ansätze finden Sie in diesem Blogbeitrag .

Tvaroh
quelle
Toll. Sie können diese Optionen auch in Ihre globale Konfigurationsdatei einfügen. für mich ist es /usr/local/etc/sbtopts(für sbt mit Homebrew auf Mac installiert).
Brian McCutchon
5

Ich hatte dieses Problem und spielte 10 Minuten lang damit herum, während ich mir Websites ansah, die versuchten, die Speichergröße zu ändern.

Es stellte sich heraus, dass ich es gelöst habe durch,

user-profile$ sbt

Dann,

sbt-project-name 0.1> clean

Das hat es für mich geklärt.

Alex Stewart
quelle
4

Es sieht für mich wie ein Speicherverlust in SBT aus, da in meinem Fall das Programm etwa 3-5 Mal erfolgreich kompiliert und ausgeführt wird, bevor die Ausnahme auftritt, die durch den Neustart von SBT behoben wird.

Die am besten geeignete Lösung scheint in der Tat der -XX:MaxPermSize=JVM-Parameter zu sein, wie Alexey Romanov vorschlägt, oder SBT regelmäßig neu zu starten, wenn dies hilfreich ist.

Es gibt aber noch einen anderen interessanten Weg: Versuchen Sie, auf Java 8 umzusteigen . AFAIK verwendet PermGen nicht mehr und ist auf diese Weise wahrscheinlich gegen diese Ausnahme immun.

Ich hoffe immer noch, dass SBT-Autoren dieses Problem in zukünftigen Versionen beheben werden.

Ivan
quelle
Java 8 verwendet also ein anderes Speichersystem?
Adrian
In J8 wird die Dauerwelle nur in die Speicherheap-Bereiche gerollt.
sksamuel
Mit Java 8 kann SBT zumindest auf meinem Mac nicht kompiliert werden. Ich muss ein Downgrade auf Java 7 durchführen.
Siyuan Ren
Vielleicht machen Sie etwas falsch, @CR Soweit ich mich erinnern kann, habe ich es damals mit Java 8 unter Linux (als es sich in der Deep Beta befand) ohne sichtbare Probleme ausprobiert und verwende es derzeit mit Java 8 unter Windows. Vielleicht könnten Sie uns die Compiler-Fehlermeldung anzeigen, die Sie erhalten?
Ivan
Vielen Dank für das Angebot, zu helfen, aber ich habe beschlossen, den komplizierten Prozess nicht noch einmal zu durchlaufen. Ich werde mich vorerst an Java 7 halten.
Siyuan Ren
2

Ich baue mit dem Jenkins sbt Plugin und hatte die gleichen Probleme. Sie wurden behoben, nachdem SBT_OPTS aus der sbt-Datei in die JVM-Flags der Jenkins-Jobkonfiguration kopiert wurde.

niebo
quelle
2

Ursprünglich mit einem Befehl wie:

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

Ich habe zuerst OutOfMemoryError: PermGen-Speicherplatz, den ich mit gelöst habe -XX:MaxPermSize, und dann OutOfMemoryError: Java-Heap-Speicherplatz , für -Xmxden Abhilfe geschaffen wurde.

In meinem Fall funktionierte ein Befehl wie dieser:

java -XX:MaxPermSize=256M -Xmx2048M -jar /path/to/sbt-launch.jar test
Jonik
quelle
0

Ändern Sie den folgenden Codeblock in der Datei sbt.sh und speichern Sie die Funktion.

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

oder

Verwenden des Terminals zum Exportieren der sbt-Konfiguration

export SBT_OPTS="-XX:+CMSClassUnloadingEnabled -XX:PermSize=1024M -XX:MaxPermSize=2048M"
KARTHIKEYAN.A
quelle