2 Stimmen

Wie vermeidet man OutOfMemoryError beim Hochladen der Datei?

Ich versuche, Bilddateien hochzuladen. Beim Hochladen von Dateien mit einer Größe von etwa 40 bis 200kb ist alles in Ordnung. Aber wenn ich versuche, eine Datei mit einer Größe von 459kb hochzuladen, wird sie manchmal hochgeladen und manchmal wird ein OutOfMemoryError angezeigt. Ich glaube nicht, dass die Dateigröße so groß ist, dass dieser Fehler ausgelöst wird. Ich verwende Resin. Ist es möglich, dass es eine Resin-Einstellung gibt, die das Hochladen von großen Dateien verhindert? Denn im Code ist nirgends eine maximale Größe für das Hochladen von Dateien festgelegt.

Hat jemand eine Idee, wie man dies vermeiden kann? Ich möchte, dass die Benutzer Bilder beliebiger Größe bis zu etwa 10 MB hochladen können.

1voto

Manuel Selva Punkte 17616

OutOfMemoryError werden von der JVM ausgelöst, wenn für eine bestimmte Aktion (z. B. die Instanziierung eines Objekts) nicht genügend Speicherplatz verfügbar ist.

Um solche Fehler zu vermeiden, können Sie den für die JVM verfügbaren Speicher beim Start erhöhen, indem Sie eine bestimmte Option für Ihre JVM verwenden (normalerweise -Xmx512m für 512 Megabyte)

In Ihrem Fall sollte ein solch kleiner Upload keinen OutOfMemoryError erzeugen, und ich empfehle die Verwendung eines Tools wie Speicher-Analysator um die Ursache des Fehlers zu ermitteln.

1voto

locka Punkte 5467

Wenn Ihnen der Speicher ausgeht, sollten Sie als Erstes prüfen, wie viel Speicher Ihre JVM zugewiesen hat. Sie sagen nicht, wie Resin ausgeführt wird, welche JVM verwendet wird oder welches Betriebssystem bzw. welcher Host verwendet wird, aber in der Regel wird eine JVM durch eine Standard-Heap-Größe und eine maximale Heap-Größe geregelt. Auf der Kommandozeile hat die Standard-JVM -Xms y -Xmx Parameter, die diese Werte bestimmen. Wenn die JVM startet, wird der Standard-Heap zugewiesen und kann bis zum Maximum wachsen. Wenn eine Zuweisung den maximalen Heap überschreitet, kann sie versuchen, alle Soft-/Swak-Referenzen und andere verfügbare Ressourcen freizugeben, eine GC zu erzwingen, aber wenn sie immer noch nicht genug Platz hat, wird sie eine OutOfMemoryException . Daher kann eine Änderung der Werte Auswirkungen darauf haben, wann dies geschieht.

Die zweite Sache, auf die Sie achten sollten, ist die Art und Weise, wie Sie den Speicher im Server zuweisen. Wenn Ihr Server z.B. einen Haufen Dinge mit starken Referenzen im Speicher hält, kann Ihnen der Speicher ausgehen. Wenn dies der Fall ist, sollten Sie stattdessen schwache Referenzen verwenden oder etwas wie Ehcache um Dinge auf die Festplatte zu verschieben. Oder wenn Ihr Servlet aufgrund eines Berechnungsfehlers MB anstelle von KB zugewiesen hat. Sie sollten ohnehin nicht versuchen, die gesamte Eingabe in den Speicher zu lesen. Angenommen, Sie implementieren ein Servlet, dann sollte das mitgelieferte ServletRequest / HttpServletRequest ermöglicht den Zugriff auf den Eingabestrom der POSTDATA und das Lesen in Chunks (z.B. 32KB auf einmal) und das Schreiben in einen Ausgabepuffer in Chunks. Als allgemeine Faustregel gilt, dass das Lesen von Eingabedaten in diskreten Brocken ohnehin die bessere Praxis ist, da Sie nicht wollen, dass nicht vertrauenswürdige Daten Ihren Server kaputt machen können, indem sie Ihnen eine riesige Datei übergeben.

0voto

Dead Programmer Punkte 12177

Legen Sie beim Starten der Anwendung die maximale und minimale Größe für Heap und reservierte Bereiche fest

mit Xmx Xms Xss

0voto

Bryce Rakop Punkte 41

Ich werde dies posten, weil es mir geholfen hat, ich habe versucht, mit Tomcat-Speicherzuweisungen zu fummeln (ich habe coldfusion und Lucee ausgeführt), aber am Ende habe ich dieses Problem umgangen, indem ich die Datei von der Festplatte statt von einem cfimage (Speicher) gelesen habe: Auszug aus der SQL-Anweisung von der Festplatte (funktioniert):

<cfqueryparam value="#fileRead("#absFilePath#")#" cfsqltype="cf_sql_blob">,

Auszug aus der SQL-Anweisung aus dem Speicher (schlägt bei größeren Dateien fehl):

#Load into cfimage
<cfimage action="read" source="#absFilePath#" name="myImage">
#Try to us it in cfqueryparam example:
<cfqueryparam value="#ImageGetBlob(myImage)#" cfsqltype="cf_sql_blob">,

Was ich SUPER seltsam finde, ist, dass ich immer noch die größeren Bilder in ein cfimage einlese, damit ich ein Thumbnail erstellen kann, und das ist in Ordnung, aber ich muss die erste Einfügung mit nur einem toBinary("Placeholder") machen und ich kann das Thumbnail einstellen, aber dann muss ich eine Aktualisierungsabfrage machen, um den "Placeholder" durch die fileRead zu ersetzen. Seltsam, aber ich habe jetzt bis zu 2MB getestet und es ist in Ordnung, während es vorher bei ~400KB fehlgeschlagen ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X