Speicherprobleme (OutOfMemory Error)

Status
Nicht offen für weitere Antworten.

Rock Lobster

Bekanntes Mitglied
Servus,

habe im Moment mit einigen ernsten Speicherproblemen zu kämpfen, und ich habe keine Ahnung, wie ich das vernünftig in den Griff kriegen soll.

Ein Beispiel:
Mein Programm bekommt 1024 MByte Speicher zugewiesen. Es lädt beim Start einige sehr große WAV-Dateien. Jetzt ist es aber so, daß das Programm es manchmal "schafft", und benötigt dann laut Taskmanager um die 960 MByte. Aber wenn ich es danach nochmal starte, kann es sein, daß es knapp 1200 MByte benötigt und sich dann mit einem OutOfMemory-Error verabschiedet, und das, obwohl es in beiden Fällen haargenau das gleiche macht.

Das ist schonmal das erste, und da sehe ich keine vernünftige Chance, das irgendwie zu beheben (wenn man mal davon absieht, daß man den zugewiesenen Speicher natürlich noch vergrößern könnte, logisch).

Das nächste ist, daß ich vor dem Einlesen einer Datei prüfen will, ob überhaupt noch Speicher zur Verfügung steht. Hier benutze ich Runtime.getRuntime().freeMemory(), aber die zeigt leider oft völlig unrealistische Werte an. Beispielsweise sagt sie, es sind noch 13 MByte frei, obwohl zu dem Zeitpunkt noch mehrere hundert hätten frei sein müssen.

Gibt es ein paar gute Strategien, um mit Speicherproblemen umgehen zu können? Gibt es todsichere Möglichkeiten, einen OutOfMemory-Error rechtzeitig und sicher zu verhindern?
Ich hoffe, ihr könnt mir helfen... :(
 
S

SlaterB

Gast
zu einem Teilpunkt:

> Beispielsweise sagt sie, es sind noch 13 MByte frei, obwohl zu dem Zeitpunkt noch mehrere hundert hätten frei sein müssen.

weil noch nicht alles allokiert wurde,
sinnvoller ist die Größe, wieviel aktuell belegt ist, wenn du dann das Maximum kennst, weißt du, wieviel noch möglich ist,

ob du die Max-Größe irgendwo komfortabel nachlesen kannst weiß ich nicht,
dürfte wohl eine System-Property sein, wenn du sie beim Start mitangibst,
oder zunächst mal fest auf 1024 MB setzen
 

MarcoBehnke

Bekanntes Mitglied
getFreeMemory zeigt Dir nur an, wieviel Speicher aktuell verfügbar ist, d.h. aber nicht, dass nicht doch noch weitere Speicher für das Programm zur Verfügung gestellt werden kann. Du kannst über die VM Parameter MIN und MAX Mem steuern. Beides auf den gleichen Wert setzen, bedeutet sofort alles zur Verfügung zu stellen.

Grundsätzlich stellt sich doch grad die Frage, warum Du überhaupt so viel auf einmal laden musst? Kannst Du das nicht Streamen/Buffern?

Erzähl mal etwas über den Anwendungsfall. OutOfMemory kannst Du leider nicht abfangen.
 

The_S

Top Contributor
Ich kenn mich jetzt mit Runtime nicht so aus, aber evtl. liefert dir getFreeMemory die höchste, noch am Stück verfügbare, Speichermenge zurück!?

Du benötigst doch bestimmt nicht alle WAV's gleichzetig oder? Dann lade doch immer nur die WAV, die momentan auch wirklich benötigt wird!
 

Rock Lobster

Bekanntes Mitglied
Naja es ist so:

Das ganze ist ein Audioplayer, der mit unterschiedlichen Strategien auf die WAV-Files zugreifen soll. Zunächst mal versucht er es mit RandomAccessFile. Wenn das nicht geht, lädt er das File als Tempfile in den Temp-Ordner und greift dann auch mit RandomAccessFile zu. Je nach Anwendungszweck können Tempfiles aber auch verboten sein, in dem Fall bleibt ihm nichts übrig als das File komplett in den RAM zu laden. Streams sind für meinen Zweck zu langsam (da auch die Bilder gerendert werden usw), deswegen MUSS das Teil in den RAM. Und erst wenn DAS auch nicht mehr hinhaut, wird als letzte Notlösung ein Stream benutzt.

So und um nun abzuprüfen, ob es überhaupt noch in den RAM paßt, brauche ich eben eine Lösung. Im Moment ist es aber so, daß einfach der Fehler auftritt und vorbei ist es. Ich habe also so gesehen gar nichterst die Möglichkeit, auf die Streams auszuweichen (weil er den OutOfMemory nicht vorhersagen kann und es eher "drauf ankommen läßt" und dann abkackt).

Daher muß ich irgendwie prüfen können, wie viel Speicher mir noch zur Verfügung steht. Leider geht das nicht, weil freeMemory() ungenaues liefert. Und usedMemory() oder so gibt's ja auch nicht. Ich kann zwar maxMemory() erfragen, aber das bringt mir nix, wenn ich den keinen usedMemory() kriegen kann.
 

Rock Lobster

Bekanntes Mitglied
@ Hobbit: Leider kommen in meinem Anwendungsfall auch WAV-Files vor, die sehr groß sind. Zwar ist das eher eine Ausnahme, aber das Teil ist keine Consumer-Anwendung sondern eher industriell, und dort sind große Datenmengen keine Seltenheit. Daher kann auch schon ein einziges WAV, das geladen wird, zu viel Speicher benötigen...
 

The_S

Top Contributor
Rock Lobster hat gesagt.:
@ Hobbit: Leider kommen in meinem Anwendungsfall auch WAV-Files vor, die sehr groß sind. Zwar ist das eher eine Ausnahme, aber das Teil ist keine Consumer-Anwendung sondern eher industriell, und dort sind große Datenmengen keine Seltenheit. Daher kann auch schon ein einziges WAV, das geladen wird, zu viel Speicher benötigen...

Wenn du WAVs Jenseits von 1 GB Speicher laden musst, und diese komplett im RAM halten willst, dann musst du so uns so den heap erhöhen ...
 
S

SlaterB

Gast
Runtime runtime = Runtime.getRuntime();
long max = runtime.maxMemory();
long free = runtime.freeMemory();
long total = runtime.totalMemory();

total ist der aktuelle belegte Speicher, äh, total - free

bei max dürften doch sogar die 1024 rauskommen?
also max - total + free für aktuell noch freien Speicher
 

Rock Lobster

Bekanntes Mitglied
@ MarcoBehnke: Auch das kommt vor.

@ Hobbit: Will ich ja eben nicht. In solch einem Fall soll das Programm merken, daß das nicht geht, und auf einen Stream zurückgreifen (was die letzte Wahl sein soll). Und genau das ist ja mein Problem.

@ SlaterB: Leider liefert mir freeMemory() falsche Ergebnisse, zumindest wollte ich abprüfen, ob der freeMemory() eine bestimmte Grenze unterschreitet. Wenn ja, sollte er NICHT anfangen, irgendwas in den Speicher zu laden. Aber schon kommt der OutOfMemory-Error... und ich hab leider auch irgendwo gelesen, daß freeMemory() nur schätzt :(

Bei maxMemory() kommen bei mir 1016 raus. Ich nehme an, daß die VM den Rest belegt oder so.
 

Kim Stebel

Bekanntes Mitglied
Code:
System.gc();
try
{
  //dein code
}
catch (OutOfMemoryError e)
{
  //pech gehabt..
}
 
S

SlaterB

Gast
@Rock Lobster
dass nur geschätzt wird, habe ich bisher nicht beobachtet (bewege mich aber nicht in den Dimensionen ;) ),
auf jeden Fall solltest du eine Sicherheitsreserve einplanen:
wenn deine 900 MB-Datei auch mal 1.2 GB belegt,
dann sage einfach: Dateien bis 500 MB passen in meine 1024 MB Speicher,
größere Dateien müssen gestreamt werden,

falls übersehen lies noch mal mal letztes (editiertes) Post zur Speicherberechnung,
max - total + free
 

Rock Lobster

Bekanntes Mitglied
OutOfMemory catchen hab ich auch schon versucht, aber in dem Moment ist es bereits zu spät. Das Programm läuft dann nicht mehr richtig. Eigentlich will ich gern vorher abfragen können, ob es zu einem OutOfMemory-Error kommen wird.
 

MarcoBehnke

Bekanntes Mitglied
public class Error
extends Throwable

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.

A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.
 
S

SlaterB

Gast
> Meines Wissens nach kann das nicht gecatched werden.

wobei aber catch(Error e) oder gar catch(Throwable t) zumindest technisch möglich ist
 

Rock Lobster

Bekanntes Mitglied
Jepp sag ich ja... da ist alles zu spät :)

Habe mir jetzt immer den free Memory ausgeben lassen nach Slater's Methode, und jetzt kackt er nie ab. Das ist auch etwas blöd ;) naja ich test jetzt mal weiter und hoffe daß er nochmal abkackt...
 

Rock Lobster

Bekanntes Mitglied
AHHHH okay ich weiß nun auch warum.

Ich vergleiche nämlich bereits mit Slater's "free" und nicht mit reinem freeMemory(), und das hat bei mir bereits bisher den "jetzt ist nicht mehr genug Speicher da"-Error ausgelöst, fälschlicherweise. Danach fängt er an, den Stream zu öffnen (anstatt das Ding in den RAM zu laden), und DORT fliegt dann ein OutOfMemory-Error, weil er beim Streamen ja auch einen Buffer anlegt...
 

Rock Lobster

Bekanntes Mitglied
Also mein Problem hat sich jetzt folgendermaßen verschoben:

Zwar scheint Slater's Methode, um den freien Speicher zu berechnen, zu funktionieren. Aber ich muß ja nun mit irgendwas vergleichen, idealerweise mit der Größe der Datei. Den Dateinamen kriege ich aber über eine URL, und da kann ich leider nicht immer eine File()-Objekt draus machen, um die Dateigröße rauszukriegen.

Also war mein Plan, einfach rechtzeitig aufzuhören, z.B. wenn "free" kleiner als 16 oder 32 MByte ist. Aber selbst dann ist es zu spät, denn er liest dann zwar nicht in den RAM sondern versucht, einen Stream zu öffnen, aber der BufferedInputStream legt ja intern auch Buffer an, und hier fliegt dann der OutOfMemory-Error.

Was ich hierbei nicht verstehe: ich glaube kaum, daß der BufferedInputStream intern mit einem Buffer von 32 MByte Größe arbeitet!?

Weiß jemand, woran das nun wieder liegen kann? Eigentlich muß doch noch genug Platz sein! Ich verwerfe sogar das zuvor eingelesene (mit flush() und null-Zuweisung) und rufe anschließend runFinalization() und gc() auf. Ich weiß, das ist keine Garantie, aber selbst wenn er's nicht macht, müßte noch genug Platz für einen InputStream sein...


EDIT: Okay, ich sehe nun, daß der gleiche Fehler auch dann kommt, wenn ich gar nicht erst in den RAM lese, sondern DIREKT als Stream öffne. Scheinbar will der Stream gleich mal viel Platz beanspruchen. Also ist der Stream schuld. Ich benutze einen BufferedInputStream, weil ich markSupported = true benötige. Gibt es Alternativen, oder ist meine Handhabung vielleicht falsch? Bzw. hatte jemand schon ähnliche Probleme, was den Stream angeht?
 
S

SlaterB

Gast
bisher war davon die Rede, dass du die ganze Datei im Speicher haben willst,
nun sind dir schon 32 MB Buffer zu groß,..
wie denn nun?

und schreibe vielleicht mal ein 50-Zeilen-Testprogramm, das eine Datei von der Festplatte einliest,
dann kann der geneigte Helfer vielleicht mal nachschauen, was da speichermäßig passiert
 

Rock Lobster

Bekanntes Mitglied
Ich hab vorhin doch ganz genau geschrieben, wie ich vorgehe. Und daß ich einen Stream öffne, wenn die Datei NICHT in den Speicher paßt. Mittlerweile habe ich eine Möglichkeit, rechtzeitig vorher abzubrechen und kann nun zum Stream übergehen. Aber da liegt ebenfalls ein Speicherproblem vor.

Ist es denn schlimm, wenn sich von zwei Problemen eines löst, bzw. daß ein zweites Problem durch die Lösung des ersten erst deutlich wird?!

Nochmal:
- Datei soll in RAM
- wenn's nicht paßt, soll ein Stream geöffnet werden
- ein Stream ist meiner Auffassung nach mehr oder weniger ein Filepointer und allenfalls ein geringer Buffer
- leider bringt selbst der Stream einen OutOfMemory-Error, selbst wenn NICHTS im RAM liegt, nur Streams vorhanden sind
- daraus schließe ich, daß die Streams unnötig viel Speicher reservieren, und ich versuche nun, das zu profilen
- danach werd ich wohl sehen, ob es wirklich an den Stream-Klassen liegt, also daß die so riesige Buffer allozieren
 

MarcoBehnke

Bekanntes Mitglied
was für einen Stream benutzt Du denn?
BufferedInputStream?

Nutzt Du den Stream denn auch, um die Daten zu streamen oder liest Du mit den Stream alles in den Hauptspeicher, um dann damit zu arbeiten?
 
S

SlaterB

Gast
@Rock Lobster

ja sorry,
ich habe halt nicht immer alles im Kopf, mein Arbeitsspeicher ist auch begrenzt,
und den Stream des Threads hier habe ich nicht nochmal komplett durchlaufen ;)
 

Rock Lobster

Bekanntes Mitglied
@ Marco: Jepp, den BufferedInputStream. Und laut Profiler belegt eine Instanz davon tatsächlich so viel Speicher, wie die Datei groß ist. Zumindest in meinem momentanen Test (da habe ich nur eine 3 MByte-Datei verwendet).

Und ich will eigentlich nur drauf streamen, sprich, er soll nur als FilePointer und -Handle fungieren, und nicht gleich den ganzen Inhalt verfügbar haben. Allerdings brauche ich eine Klasse, bei der "markSupported" gegeben ist. Gibt es Alternativen? Wie gesagt, RandomAccessFile scheidet ja schon aus, das ist nämlich eine der ersten Möglichkeiten, und gestreamt wird ja nur, wenn diese Möglichkeit, die Tempfile-Möglichkeit und die RAM-Möglichkeit fehlschlagen.

@ SlaterB: Jo, ich sehe, wir verstehen uns ;)
 

Rock Lobster

Bekanntes Mitglied
So langsam habe ich den Verdacht, daß "markSupported" nur deswegen der Fall ist, WEIL er so viel buffert und darin dann beliebig rumspringen kann. Aber jedesmal den Stream neu zu initialisieren ist eben nicht besonders performant.

Schein aber, als müßte ich wohl wirklich darauf ausweichen. Einen normalen Stream nehmen, den ich dann jedesmal neu initialisieren darf, das ist dann zwar saulangsam, aber immerhin bekomme ich keine Speicherprobleme.

@ Marco: Danke für die Tips, leider habe ich damit schon gearbeitet und es bringt nichts. AudioInputStream arbeitet im Grunde genau wie der BufferedInputStream, d.h. ich hatte dieselben Probleme damals. Den AudioFileReader hingegen kann ich nicht nutzen, weil überall, wo dieser funktionieren würde, funktioniert auch das RandomAccessFile... :/
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
A Parser verursacht Speicherprobleme auf Server Allgemeine Java-Themen 2
M Bilderstapel schnell durchschalten? Speicherprobleme. Allgemeine Java-Themen 3
S Speicherprobleme bei zwei laufenden JAVA-Applikationen Allgemeine Java-Themen 10
C Eclipse OutOfMemory nach dem exportieren Allgemeine Java-Themen 4
A Interpreter-Fehler OutOfMemory Exception mit Base64 decode Allgemeine Java-Themen 3
J BufferedReader OutOfMemory umgehen? Allgemeine Java-Themen 10
K Input/Output ObjectInputStream.HandleTable OutOfMemory Allgemeine Java-Themen 8
N OutOfMemory Allgemeine Java-Themen 5
G OutOfMemory Error bei Zahlenkonvertierungsprogramm Allgemeine Java-Themen 5
B Java OutOfMemory Error verhindern, Resourcenbedarf präventiv abschätzen? Allgemeine Java-Themen 19
M OutOfMemory Exception? Allgemeine Java-Themen 12
N OutOfMemory nur wenn -Xmx gesetzt ist?! Allgemeine Java-Themen 6
E java.lang.outofmemory über windows-cmd ändern Allgemeine Java-Themen 6
V JVM OutofMemory Linux geht, windows nicht Allgemeine Java-Themen 3
H java heap space (outofmemory error) Allgemeine Java-Themen 3
J ObjectInputStream und OutOfMemory Allgemeine Java-Themen 10
K OutOfMemory beim Entzippen Allgemeine Java-Themen 6
G IOException error 2 Allgemeine Java-Themen 3
urmelausdemeis Exception in thread "main" java.lang.Error: Unresolved compilation problem: Allgemeine Java-Themen 7
Mick P. F. Wie kriege ich die Fehlermeldung "java: symbol lookup error: ..." weg? Allgemeine Java-Themen 11
S An internal error occurred during: Launching null argument Allgemeine Java-Themen 1
S Gradle "schluckt" output und error Allgemeine Java-Themen 1
Bluedaishi Access violation error Allgemeine Java-Themen 2
M Jdeps-Error durch multi-release Allgemeine Java-Themen 6
Xge For/Array Error: IndexOutOfBounds Allgemeine Java-Themen 4
S CMD Compiler Error Allgemeine Java-Themen 13
L Compiler-Fehler Eclipse Error: A JNI error has occured Allgemeine Java-Themen 3
T Eclipse IDE Plugin Error Log Allgemeine Java-Themen 0
Robat JNI - Fatal Error Allgemeine Java-Themen 5
S LinkedList Error Allgemeine Java-Themen 4
F String Error Allgemeine Java-Themen 7
K Error Allgemeine Java-Themen 2
G Error Meldung bei Gomoku Spiel Allgemeine Java-Themen 9
J LWJGL 3 Error Code 1282 Allgemeine Java-Themen 4
N Maven ObjectMapper Error wenn das File gespeichert wird Allgemeine Java-Themen 0
D Datentypen Cache Images Heap Space Error Allgemeine Java-Themen 7
D Java Error String kann nicht in Int umgewandelt werden Allgemeine Java-Themen 2
L Exception/Error auf JDialog umleiten Allgemeine Java-Themen 2
G Java Error (Exception_acces_violation) Allgemeine Java-Themen 2
G Java Error (Exception_acces_violation) Allgemeine Java-Themen 0
Thallius Simple JSON Parser Error null Allgemeine Java-Themen 6
F Compiler-Fehler Hilfe bei Startup error Allgemeine Java-Themen 3
M List casting error Allgemeine Java-Themen 3
F Java Error, bei Installation, Start und dem Control Panal Allgemeine Java-Themen 8
A ausführbare jar Error Allgemeine Java-Themen 2
F Error Logging - best practices? Allgemeine Java-Themen 3
P JDK installieren Error: Could not find or load main class HelloWorld.java Allgemeine Java-Themen 3
D Java error Allgemeine Java-Themen 2
J JVM Launcher Error Allgemeine Java-Themen 30
Jats Programm mit CMD Befehl hängt sich auf oder gibt error = 5 aus Allgemeine Java-Themen 4
I Java Ordner kopieren [Error] Allgemeine Java-Themen 6
Jats ArrayList-Error Index: 1 Size:1 - Bitte um Hilfe Allgemeine Java-Themen 36
B Fatal error der JVM Allgemeine Java-Themen 9
N xml fatal error umgehen Allgemeine Java-Themen 14
M Webservice mit Axis2 und Eclipse - Error Allgemeine Java-Themen 2
S JNI - Fatal Error Allgemeine Java-Themen 2
D Java Heap error trotz anpassungen mit -xmx Allgemeine Java-Themen 4
R VM-Error - BadWindow (invalid Window parameter) Allgemeine Java-Themen 4
F Look And Feel Error Allgemeine Java-Themen 30
X Error bei der Programmierung eines Sortieralgorithmus Allgemeine Java-Themen 2
B maven 2 error bei plugin download Allgemeine Java-Themen 7
hdi Heap Sapce Error bei sehr großem String Allgemeine Java-Themen 5
D Java Error / Fehler Allgemeine Java-Themen 2
A JNI unsatisfied linker error Allgemeine Java-Themen 2
R Syntax Error, der keiner sein sollte Allgemeine Java-Themen 12
S Error aus der Konsole auslesen Allgemeine Java-Themen 2
G Text aus Zwischenablage in JTextarea -> JDBC Error Allgemeine Java-Themen 3
A Synatx Error, wo gar keiner ist ? Allgemeine Java-Themen 2
T Syntax Error Allgemeine Java-Themen 9
B JMF Installations Error Allgemeine Java-Themen 2
O java StreamCorrupted Error beim Belegen einer JTextpane Allgemeine Java-Themen 5
J Fatal Error Allgemeine Java-Themen 8
G Error: Hashtable Type safety: The method put(Object, Object) Allgemeine Java-Themen 6
J "Empty-String" Error Allgemeine Java-Themen 6
W Runtime Error216 Runtime error 217 Allgemeine Java-Themen 6
J Interpreteraufruf bring Error obwohl dies nicht sein dürfte. Allgemeine Java-Themen 24
G Error: java.lang.OutOfMemoryError: Java heap space Allgemeine Java-Themen 2
S Syntax Error, insert "AssignmentOperator Expression&amp Allgemeine Java-Themen 3
T Konsole "Fehlermeldung": error hereerror here Allgemeine Java-Themen 4
M typecast error Allgemeine Java-Themen 14
R Problemchen (unexpected error) Allgemeine Java-Themen 2
K error=2 (Datei nicht gefunden) - Datei ist aber da! Allgemeine Java-Themen 10
B unchecked cast Error Allgemeine Java-Themen 2
I Error: Unable to realize com.sun.media.amovie.AMController Allgemeine Java-Themen 3
M JButton verursacht einen HeapSpace Error? Allgemeine Java-Themen 6
B Syntax error on token ,VariableDeclaratorId expected after. Allgemeine Java-Themen 3
F Jar mit Abhängigkeiten ausführen -> NoClassDefFound Error Allgemeine Java-Themen 16
M strange error Allgemeine Java-Themen 3
S HTTPUnit Test Fehler: Error on HTTP request: 500 Internal Er Allgemeine Java-Themen 9
R .jar Executable - JVM Launcher: Fatal error Allgemeine Java-Themen 9
W Wie fange ich einen Error ab? Allgemeine Java-Themen 6
R Server Error 503 Allgemeine Java-Themen 4
D java.lang.error Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben