OutOfMemoryError: PermGen Space - Jasper-Bericht mit Spring läuft auf Tomcat

8

Unsere Webanwendung hat eine komplizierte Situation

Es ist eine Spring-Anwendung, die von STS / Tomcat 7 entwickelt wurde. Nachdem die Anwendung mit Jasper report 4.6.0 integriert wurde, wird immer 'OutOfMemoryError: PermGen Space' geworfen. Dann ist der einzige Weg, es zum Laufen zu bringen, die Anwendung neu zu starten. Aber nach einer Weile passiert es wieder. Hier ist Protokoll vor der Ausnahme:

%Vor%

Hier ist ein Abschnitt innerhalb der Ausnahme, wo ich etwas über Jasper gefunden habe:

%Vor%

Hier sind ein paar Befunde, wenn die Situation eintritt:

  1. Das Problem kann auf der Seite ohne Jasper Report-Komponenten auftreten. Es scheint, dass die Jasper Report-Bean versucht, immer eine tag lib zu finden, wenn a request is processed by the back end and responded to the front end . Normalerweise von Log-Datei kann ich sehen, oben Ausnahme wird nicht werfen, bis alle Back-End-Operationen (JPA-Verwaltung) abgeschlossen sind

  2. Wenn ich log4J im Debug-Modus starte, sehe ich eine Unmenge von Informationen, die etwas wie das Parsen / Rendern aller Komponenten von Jasper template (Textfelder, Stift, Box ...) anzeigen. Es gibt einen kleinen Ausschnitt aus dem riesigen Protokoll:

    %Vor%

    Dieses Protokoll wird dennoch generiert, wenn eine Anfrage an die Seite gesendet wird, die keine Jasper-Komponente enthält.

Ich habe einige Nachforschungen angestellt, kann aber immer noch keine Lösung für dieses Problem finden.

  1. Die erste Frage ist sogar, dass es in der Anwendung ein jasperreport bean gibt, warum es immer läuft, wenn es nicht gerade mit dem aktuellen Dienst auto- wiert ist (dh die aktuelle Seite hat keine Jaspis-Komponente). Gibt es eine Lösung / Antwort auf diese Situation?

  2. Auch von der Ausnahmebedingungsnachricht      Mindestens eine JAR wurde nach TLDs durchsucht, enthielt jedoch keine TLDs.      bei org.apache.jasper.compiler.JDTCompiler.generateClass (JDTCompiler.java:442)

    sollte von Tomcat und Tomcat never contains any JSTL jar kommen, dann gehe ich davon aus, dass es keine passende TLD zum parsen von jasper report finden kann, also mache einen vollständigen Scan aller jars. Wenn ja, wie kommt es dann, gibt es eine große Menge von Debug-Logs von org.apache.commons.digester.Digester scheint tatsächlich beschäftigt bei der Analyse der Jaspis-Vorlage?

Im Allgemeinen machen Sie diesen Thread ist nur versuchen, eine Lösung für das Problem zu finden, und auch eine Antwort zu finden, warum Jasper ist so aktiv an einem Ort erfordert es nicht, und wie können wir Tomcat richtig analysiert die Vorlagen?

Entschuldigen Sie sich wenn zu ausführlich, und danke für irgendwelche Hinweise.

    
Dreamer 17.10.2012, 20:42
quelle

5 Antworten

8

Ich danke Ihnen allen, dass Sie eine Lösung für dieses Problem gefunden haben. Ich habe das Problem speziell für meine Situation identifiziert und hier ist die Lösung:

Verwenden Sie .jasper anstelle von .jrxml als Vorlage!

Wie wir wissen, .jasper ist eine kompilierte Vorlage sowie .jrxml ist ASCII-Quellcode für die Vorlage, so dass, wenn wir rohe Quellcodedatei (jrxml) als Vorlage in der aktuellen Feder-Anwendung verwenden, dann mindestens Frühjahrsrahmen arbeiten muss die Quellcodedatei kompilieren. Das ist eine Frage der Effizienz, die dem Spring-Framework überlassen wird, da es die Jaspis-Bean ist, die Kompilierung zu handhaben, und es ist nicht garantiert, dass die Kompilierung nur einmal ausgeführt wird und nur beim Start der Anwendung geschieht.

Kurz gesagt, nachdem alle Vorlagen durch die .jasper-Datei ersetzt wurden, wurde die Protokollgröße erheblich reduziert und das Problem mit dem nicht mehr benötigten Arbeitsspeicher wurde nicht mehr erkannt. Ich nehme an, dass der Spring-Container eine Menge Ressourcen verbraucht, um jrxml zur Laufzeit in Jaspis zu kompilieren. So könnte etwas von Jasper oder Spring verbessert werden ....

    
Dreamer 19.03.2013, 16:35
quelle
7

Die Ausnahme tritt auf, wenn zu viele .class-Dateien im permgen-Bereich in der JVM vorhanden sind, die aufgrund ihrer Verweise auf ein Objekt außerhalb von AppClassLoader nicht als Garbage-Collection behandelt werden können. Es weist im Allgemeinen darauf hin, dass ein gewisser Speicherverlust Ihre Anwendung auslöscht.

Dieser Beitrag hat eine klare Erklärung von java.lang. OutOfMemoryError: PermGen Space Error und ein folgender Beitrag enthält Vorschläge wie man es repariert. Eine ähnliche (aber nicht exakt dieselbe) Frage wurde gestellt auf SO, lassen Sie wissen, wenn Sie es verpasst haben. Ich hoffe es hilft.

Da jakub die Einstellung -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled erwähnt hat oder einen höheren Wert für XX:MaxPermSize festgelegt hat, könnte es für Sie funktionieren. Aber nach dem, was ich gelesen habe, scheint es keine dauerhafte Lösung zu sein. (Ich bin kein Meister darin:)).

    
shazinltc 18.10.2012 02:38
quelle
2

Versuchen Sie, diese Parameter in Ihrer VM festzulegen. Diese sollten die GC-Reinigung Ihrer PermGen ermöglichen.

%Vor%     
jakub.petr 17.10.2012 21:06
quelle
2

Ich habe eine Webanwendung entwickelt, die JasperReports 4.5.1 verwendet

Ich benutze Tomcat 6.0.26 als Container. (Win7, JDK 1.6.0_25)

Wenn Sie den Tomcat herunterfahren, werfen Sie:

Die Webanwendung hat ein ThreadLocal mit dem Schlüssel [net.sf.jasperreports.engine.util.JRFontUtil $ 1] (Wert [net.sf.jasperreports.engine.util.JRFontUtil11@7892f1]) und einem Wert von erstellt Geben Sie [java.util.HashSet] (Wert [[]]) ein, aber es konnte nicht entfernt werden, wenn die Webanwendung beendet wurde. Dies führt sehr wahrscheinlich zu einem Speicherverlust.

Bitte besuchen Sie die Website:

Ссылка

    
sfxm 01.11.2012 10:00
quelle
0

Da der PermGen hauptsächlich Klassenmetadaten und konstante und internierte Strings enthält, können Sie in zwei Richtungen suchen:

  • überprüfen Sie, dass die Webapp nicht (zu viele) unbrauchbare Jars enthält, die durch das Scannen geladen werden

  • Sehen Sie, ob Sie viele konstante Strings haben (viele große JSPs zum Beispiel), die einen Heap-Dump verwenden, oder ob Ihr Code String.intern ()

  • verwendet

Tatsächlich haben Sie nicht angegeben, welche Version von Java Sie verwendet haben: Bei Java 7 ist die Zeichenfolge möglicherweise kein Problem.

Sie können die Anwendung mit JVisualVM mithilfe des VisualGC-Plugins beobachten, um den Status der Generationen, die Anzahl der geladenen Klassen und ob es zum Zeitpunkt des OOM einen Anstieg gibt oder ob es sich um einen Anstieg handelt ein langsamer Aufbau.

    
Frank Pavageau 17.10.2012 21:25
quelle