Apache fop - OutOfMemoryError

Hein_nieH

Bekanntes Mitglied
Hallo,

ich versuche mit der Bibliothek von Apache fop eine pdf-Datei via xsl-fo aus einer große XML-Datei zu generieren.
Hierbei erhalte ich eine Outofmemoryerror-Exception.

Ursache ist wohl das die Größe des Java Heap wohl zu gering ist.
Meine Frage: Gibt es eine Möglichkeit softwaremäßig den Java Heap zu vergrößern?

Meine xml-Datei ist etwa 1 MB groß.

Über eine fachkundige Antwort würde ich mich sehr freuen.

Gruss Hein_nieH
 
Du kannst beim Start dem java Optionen mitgeben. -Xmx<Größe> also z.B. -Xmx1024m um die Größe auf 1024 MB zu setzen.

Wichtig ist, dass diese Einstellung vor der Nennung des Jar Files oder der Main Klasse kommen muss, damit es nicht als Parameter der Applikation verstanden wird.
 
Eine XML-Datei mit einer Größe von 1 MB ist nichts wirklich großes. Zusätzlich zur Einstellung der Java-Heap-Größe kann man noch folgendes tun um Speichernutzung und Performanz zu verbessern.
  • Um den Speicherverbrauch zu verringern, sollten wann immer möglich, die einzelnen beteiligten Komponenten (Parser, XSL-Transformer, SQL-Datenquelle usw.) über SAX gekoppelt werden.
  • Je nach Ziel-OutputStream (z.B. bei einem FileOutputStream, nicht bei ByteArrayOutputStream) kann es die Leistung erheblich verbessern, wenn der Stream gepuffert wird: out = new java.io.BufferedOutputStream(out);
  • Wenn dasselbe Stylesheet mehrfach verwendet werden soll, kann ein JAXP Templates-Objekt eingerichtet werden und es ist dann bei jeder XSL-Transformation wiederverwendbar.
  • Verwendung eines XSLT-Compiler wie XSLTC, der in Xalan-J enthalten ist.
  • Vererbung von Eigenschaften konsequent zu nutzen.
 
Hallo,

danke für die Antworten.
In meinem Fall habe ich eine ausführbare jar-Datei.
Gibt es in diesem Fall auch eine Möglichkeit die xmx-Einstellungen für Java vornehmen?

@Oneixee5: Die Hinweise habe ich schon weitestgehend befolgt.

Gruss Hein_nieH
 
Hallo

der Hinweis war schon mal nicht schlecht.
Ich habe das Problem gelöst, in dem ich in den Umgebungsvariablen
die Variable _JAVA_OPTIONS mit dem Wert -Xmx1024M gesetzt habe.

Jetzt läuft die ausführbare jar so wie es angedacht war, d.h "grosse" xml werden via xslt in pdf gewandelt ohne
das eine OutOfMemoryError Exception geworfen wird.

Gruss Hein_nieH
 
Es kommt etwas darauf an wie man _JAVA_OPTIONS verwendet. Ich halte nicht viel davon die maximale Heap-Größe per _JAVA_OPTIONS Umgebungsvariablen zu setzen. Jetzt verwenden alle Java Programme die Größe von 1GB, ob sie das benötigen oder nicht. Selbst wenn man explizit eine andere Heap-Größe auf der Kommandozeile angibt. Es könnte ja sein, dass eine andere Anwendung z.B.: 2GB verwenden muss...
 
Es kommt etwas darauf an wie man _JAVA_OPTIONS verwendet. Ich halte nicht viel davon die maximale Heap-Größe per _JAVA_OPTIONS Umgebungsvariablen zu setzen. Jetzt verwenden alle Java Programme die Größe von 1GB, ob sie das benötigen oder nicht. Selbst wenn man explizit eine andere Heap-Größe auf der Kommandozeile angibt. Es könnte ja sein, dass eine andere Anwendung z.B.: 2GB verwenden muss...
Bash:
$ java -cp . test/Main
current heap size: 242,0 MiB
    max heap size: 3,8 GiB
   free heap size: 239,5 MiB

$ java -Xmx256m -cp . test/Main
current heap size: 242,0 MiB
    max heap size: 256,0 MiB
   free heap size: 239,5 MiB

$ export _JAVA_OPTIONS=-Xmx1g

$ java -Xmx256m -cp . test/Main
Picked up _JAVA_OPTIONS: -Xmx1g
current heap size: 242,0 MiB
    max heap size: 1,0 GiB
   free heap size: 239,5 MiB

$ java -Xmx2g -cp . test/Main
Picked up _JAVA_OPTIONS: -Xmx1g
current heap size: 242,0 MiB
    max heap size: 1,0 GiB
   free heap size: 239,5 MiB

Java:
public final class Main {

    public static void main(final String[] args) {

        // Get current size of heap in bytes
        final long heapSize = Runtime.getRuntime().totalMemory();
        System.out.println("current heap size: " + humanReadableByteCount(heapSize));

        // Get maximum size of heap in bytes. The heap cannot grow beyond this size.
        // Any attempt will result in an OutOfMemoryException.
        final long heapMaxSize = Runtime.getRuntime().maxMemory();
        System.out.println("    max heap size: " + humanReadableByteCount(heapMaxSize));

        // Get amount of free memory within the heap in bytes. This size will increase
        // after garbage collection and decrease as new objects are created.
        final long heapFreeSize = Runtime.getRuntime().freeMemory();
        System.out.println("   free heap size: " + humanReadableByteCount(heapFreeSize));

    }

    public static String humanReadableByteCount(final long bytes) {
        final long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes);
        if (absB < 1024) {
            return bytes + " B";
        }
        long value = absB;
        final CharacterIterator ci = new StringCharacterIterator("KMGTPE");
        for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) {
            value >>= 10;
            ci.next();
        }
        value *= Long.signum(bytes);
        return String.format("%.1f %ciB", value / 1024.0, ci.current());
    }

}
 
Ok, das stimmt.

Ich versuche noch eine andere Lösung zu finden.
Das starten per Kommandozeile wie z.B. java -Xmx:1024m -Xms:1024m -jar myjar.jar

Hat bei mir nicht funktioniert (Fatal error). :-(

Gruss Hein_nieH
 

Zurück
Oben