Java nicht genügend Arbeitsspeicher Ausnahme

7

Ich verwende eine Java Web Application in Tomcat. Die Anwendung verwendet Quartz-Framework, um den Cron-Job in regelmäßigen Abständen zu planen. Dieser Cron-Job beinhaltet das Parsen einer 4+ MB XML-Datei, die ich mit der JDOM-API mache. Die XML-Datei enthält etwa 3600 zu analysierende Knoten und folglich Daten, die in DB aktualisiert werden, was ich sequentiell mache.
Nachdem fast die Hälfte der Datei analysiert wurde, löst meine Anwendung eine Ausnahme wegen zu wenig Arbeitsspeicher aus. Der Stack-Trace des gleichen ist:

%Vor%

Das bringt sogar meinen Kater zum Absturz. Können Sie mir bitte helfen, das Problem zu diagnostizieren? Ich habe sogar Profiling in den Netbeans für das selbe aktiviert, aber es scheint, dass sogar das abgestürzt ist. Ich habe den Standardspeicher für Tomcat reserviert. Gibt es ein Speicherleck? Meine DB ist postgres und JDK ist 1.6.0_15.

Danke, Amit

    
Amit 30.11.2009, 09:15
quelle

9 Antworten

9

Versuchen Sie, die RAM-Zuweisung für Ihre JVM zu erhöhen. Es sollte helfen.

Fix für Eclipse: Sie können dies in der Eclipse-Einstellung wie folgt konfigurieren

  1. Windows - & gt; Einstellungen (auf Mac: Eclipse - & gt; Einstellungen)
  2. Java - & gt; Installierte JREs
  3. Wählen Sie die JRE und klicken Sie auf Bearbeiten
  4. Geben Sie im Feld "VM-Standardargumente" den Wert -Xmx1024M ein. (oder Ihre Speicherpräferenz, für 1 GB RAM 1024)
  5. Klicken Sie auf Fertig stellen oder OK.
user1374131 09.01.2013 05:53
quelle
5

Jedes Mal, wenn Sie ein DOM zum Parsen einer XML-Datei verwenden, laden Sie die gesamte Datei in den Speicher, und die DOM-Infrastruktur verwendet ungefähr dieselbe Größe, um sie zu verarbeiten, sodass sie etwa doppelt so viel Speicher belegt wie Ihre Datei.

Sie müssen SAX, einen ereignisbasierten Parser, verwenden. Während dies beim ersten Mal schwer zu verstehen sein kann, ist es sehr speichereffektiv, da es nur den aktuellen Parsing-Knoten im Speicher hält.

Scheint, dass Java einige SAX-Implementierungen hat, wie StAX , ich hoffe, es hilft.

    
Rubens Farias 30.11.2009 09:22
quelle
3

Versuchen Sie, die RAM-Zuweisung für Ihre JVM zu erhöhen. Es sollte helfen.

Fix für Eclipse: Sie können dies in der Eclipse-Einstellung wie folgt konfigurieren

Windows - & gt; Einstellungen (auf Mac: Eclipse - & gt; Einstellungen) Java - & gt; Installierte JREs Wählen Sie die JRE aus und klicken Sie im Feld "VM-Standardargumente" auf Bearbeiten. --Xms256m -Xmx512m -XX: MaxPermSize = 512m -XX: PermSize = 128m. (oder Ihre Speicherpräferenz, für 1 GB RAM ist seine 1024) Klicken Sie auf fertig oder OK.

    
Manjush 08.05.2014 10:01
quelle
2

Das Parsen von XML ist eine ziemlich teure Aufgabe. Der durchschnittliche DOM-Parser würde bereits mindestens fünfmal soviel Speicherplatz benötigen wie das XML-Dokument groß ist. Sie sollten diese Tatsache ebenfalls berücksichtigen. Um sicherzustellen, dass an keiner anderen Stelle ein Speicherverlust auftritt, der den Speichermangel für den XML-Parser verursacht hat, müssen Sie einen Profiler ausführen. Geben Sie ihm mehr Speicher, verdoppeln Sie den verfügbaren Speicher und profilieren Sie ihn. Wenn Sie die Ursache behoben und das Leck behoben haben, können Sie einfach in den "Standardspeicher" zurückfallen und den Test wiederholen. Oder wenn es wirklich keinen Ausweg gibt, dann gib einfach alles ein bisschen mehr Speicher als Standard, damit alles passt.

Sie können auch einen effizienteren XML-Parser verwenden, zum Beispiel VTD-XML (< eine href="http://vtd-xml.sourceforge.net/"> Homepage hier , Benchmarks hier ).

    
BalusC 30.11.2009 11:31
quelle
2

Sie müssen dem PermGenSpace der Tomcat-JVM mehr Platz zuweisen.

Dies kann mit dem JVM-Argument erfolgen: -XX:MaxPermSize=128m

Standardmäßig ist der PermGen-Bereich 64M (und er enthält alle kompilierten Klassen. Wenn Sie also eine Menge jar (Klassen) in Ihrem Klassenpfad haben, können Sie diesen Platz tatsächlich füllen).

Nebenbei bemerkt können Sie die Größe des PermGen-Bereichs mit JVisualVM überwachen und Sie können sogar seinen Inhalt mit YourKit Java Profiler

    
Sujith PS 30.08.2013 10:24
quelle
1

Haben Sie versucht, die maximale Heap-Größe zu vergrößern, um zu sehen, ob das Problem dann immer noch auftritt? Es könnte überhaupt nicht einmal ein Leck geben. Es kann nur sein, dass die Standard-Heap-Größe (64m auf Windows glaube ich) für diesen bestimmten Prozess nicht ausreicht.

Ich finde, dass ich fast immer jeder Anwendung geben muss, die Tomcat mehr Heap- und Perm-gen-Speicherplatz als die Standardwerte verwendet, oder ich bekomme Probleme mit zu wenig Arbeitsspeicher. Wenn Sie Hilfe beim Anpassen der Speichereinstellungen benötigen, sehen Sie sich diese Frage .

    
Jason Gritman 30.11.2009 11:54
quelle
0

Sind Sie sicher, dass es dort irgendwo keine rekursive Array-Kopie gibt? Vielleicht in verschiedenen Threads?

    
lorenzog 30.11.2009 09:23
quelle
0

Ich werde diesen Punkt über die Datei und das DOM, die sehr viel Speicher beanspruchen, zurückstellen. Ich frage mich auch, wenn ich das sehe:

%Vor%

Was macht das Kopieren? Ich frage mich, ob in deinem Code noch etwas anderes passiert.

Wenn Sie so weit gekommen sind, deutet das darauf hin, dass Sie die Datei und das DOM erfolgreich gelesen haben und beginnen, in die Datenbank zu schreiben. Der Dateispeicher sollte bereits zurückgewonnen werden.

Ich würde vorschlagen, die Erinnerung mit VisualGC zu untersuchen, damit Sie sehen können, was vor sich geht.

    
duffymo 30.11.2009 11:02
quelle
0

Sie können Ihre Anwendung mit folgendem Befehl ausführen: -XX: + HeapDumpOnOutOfMemoryError. Dies führt dazu, dass die JVM einen Heapspeicherauszug erstellt, wenn nicht genügend Speicher vorhanden ist. Sie können etwas wie MAT oder JHAT verwenden, um zu sehen, welche Objekte festgehalten werden. Ich schlage vor, das Eclipse-Speicheranalyse-Tool (MAT) auf dem generierten Heap-Dump zu verwenden, da es ziemlich einfach zu verwenden ist: Ссылка

Natürlich müssen Sie eine Idee haben, welche Objekte herumhängen können, damit dies nützlich ist. DOM-Objekte? Ressourcen aus früheren Ladungen von XML-Dokumenten? Datenbankverbindungen? MAT ermöglicht es Ihnen, die Verweise auf ein Stammobjekt von einem Objekt zurückzuverfolgen, von dem Sie vermuten, dass es als Garbage Collector erfasst wurde.

    
Matt Crinklaw-Vogt 30.11.2009 16:02
quelle