ImageBuffer

headnut

Gesperrter Benutzer
Guten Abend

Infolgendem Code definiere ich drei Bilder Images um damit arbeiten zu können!


Code:
public void createBufferedImages() {
        biSrc = new BufferedImage(speicherbares.getWidth(this),
                                  speicherbares.getHeight(this),
                                  BufferedImage.TYPE_INT_RGB);

        big = biSrc.createGraphics();
        big.drawImage(speicherbares, 0, 0, this);

        biDest = new BufferedImage(speicherbares.getWidth(this),
                                   speicherbares.getHeight(this),
                                   BufferedImage.TYPE_INT_RGB);
        bi = biSrc;
    }

Wenn ich diese nun ein zweite mal definieren möchte kommt vollgende Meldung:


Code:
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Kann ich diesen Buffer irgendwie leeren wenn ich das Bild abspichere? Weil 56mB reichen nicht aus um zwei mal den Puffer zu füllen...

Ist ein flush villeicht das richtige?
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Wenn die Bilder sehr groß sind, kann man irgendwann nur mit
java -Xmx1000m DasProgramm
den SPeicher hochsetzen.

Ansonsten schauen, dass keine unbenutzten Referenzen mehr auf die Bilder existieren. Das KÖNNTE einer der GANZ wenigen Spezialfälle sein, wo ein explizites "null"-Setzen hilfreich ist:

Java:
private BufferedImage image = new BufferedImage(large,large,xxx);

void updateImage()
{
    BufferedImage newImage = new BufferedImage(large, large,xxx); // Verursacht OutOfMemoryError
    image = newImage;
...
}

->


Java:
private BufferedImage image = new BufferedImage(large,large,xxx);

void updateImage()
{

    image = null; // Explizit auf null setzen, damit der GC es sich holen kann

    BufferedImage newImage = new BufferedImage(large, large,xxx); 
    image = newImage;
...
}


Aber ob das passt weiß man nicht, und es sollte nicht notwendig sein.
 
S

SlaterB

Gast
ob es damit funktioniert kann man nicht sicher sagen, wer weiß wie intern alles vernetzt ist,
aber dass es hier notwendig ist kann man doch ganz gut unterschreiben, wieso nicht?

mal abgesehen davon dass mehr Speicher eine Lösung ist und der Compiler vielleicht so intelligent ist von selber zu erkennen dass sich niemand mehr für das alte Bild interessiert werden ohne '= null' beide Bilder zu einem bestimmten Zeitpunkt garantiert gleichzeitig im Speicher vorhanden sein,
mit '= null' ist das vielleicht nicht so, klingt für mich sinnvoll
 

Marco13

Top Contributor
Wenn man wirklich ein Bild erstellt, das ~900 MB groß ist, und damit auf einem 32bitter schon den Speicher so zukloppt, dass kein zweites solches Bild mehr erstellt werden kann, kann es zwar helfen, aber ... ich finde (etwas unfundiert) dass das ein bißchen "kaschierend" wirkt. Aber deswegen wäre es natürlich nicht "falsch" oder "illegitim".
 

headnut

Gesperrter Benutzer
Kann ich diesen Befehl irgendwie über eclipse mitgeben? java -Xmx1000m DasProgramm ??

Die Bilder auf =null; zu setzen hat leider nichts gebracht...

Das Problem ist tatsächlich dass ich sogar 4 Bildreferenzen habe die miteinander geladen werden.
 
Zuletzt bearbeitet:

jgh

Top Contributor
Run -> Run Configurations -> (Reiter) (X)=Arguments -> unter VM arguments dann den entsprechenden Wert bspw. -Xmx1024m eintragen und Apply(ien)

oder???
 

headnut

Gesperrter Benutzer
Jo hat perfekt funktioniert! nur mein Problem um 10 Bildbarbeitungen verschoben...

Die Meldung kommt immer noch einfach später... Ich muss einen anderen Lösungsansatz suchen:-(
 

jgh

Top Contributor
Hast du evtl. schonmal probiert, [c]System.gc();[/c] nach dem null-Setzen aufzurufen?

PS: Ja ja ich weiß, dass es sich nur um die Bitte an den GC handelt, mal aufzuräumen...aber manchmal hilft bitten ja auch :)
 

headnut

Gesperrter Benutzer
Hilft leider nicht

Ich kann dem Speicher zuschauen wie er sich füllt:-(

Es muss doch eine vernünftige Lösung geben mit dem BufferedImages?

Ich checks nicht:-( kann ich irgendwie die Ram löschen?
 
Zuletzt bearbeitet:

Ariol

Top Contributor
Hast du mal versucht dein Bild direkt zu überschreiben?

Java:
private BufferedImage image = new BufferedImage(large,large,xxx);
 
void updateImage()
{
    image = new BufferedImage(large, large,xxx);
}
 

headnut

Gesperrter Benutzer
Code:
biDest = new BufferedImage(speicherbares.getWidth(this),
                                   speicherbares.getHeight(this),
                                   BufferedImage.TYPE_INT_RGB);


Mach ich ja, oder nicht?
 

headnut

Gesperrter Benutzer
Ich lade die die Images und nachher werden Sie generiert!

beim abspeichern werden die Variablen auf null gesetzt aber de speicher bleibt voll

Code:
	public void loadImage() throws IOException {
    	
		speicherbares = ImageIO.read(scannerBild);
        MediaTracker mt1 = new MediaTracker(this);
        mt1.addImage(speicherbares, 1);
        try {
            mt1.waitForAll();
        } catch (Exception e) {
            System.out.println("Exception while loading.");
        }
 
        if (speicherbares.getWidth(this) == -1) {
            System.out.println("No jpg file");
            System.exit(0);
        }
    }
	
    public void createBufferedImages() {
        biSrc = null;
    	biDest = null;
    	bi = null;
    	
    	biSrc = new BufferedImage(speicherbares.getWidth(this),
                                  speicherbares.getHeight(this),
                                  BufferedImage.TYPE_INT_RGB);

        big = biSrc.createGraphics();
        big.drawImage(speicherbares, 0, 0, this);

        biDest = new BufferedImage(speicherbares.getWidth(this),
                                   speicherbares.getHeight(this),
                                   BufferedImage.TYPE_INT_RGB);
        bi = biSrc;
        
    }
 

Ark

Top Contributor
Kann es sein, dass der MediaTracker noch Referenzen auf das Bild hat? Oder diese Variable "speicherbares": vllt. solltest du die mal auf null setzen?

Ark
 
S

SlaterB

Gast
speicherbares wird noch gebraucht, um dieses geht es wohl kaum,

der Code ist nicht genug oder bitte folgendes testen:
Java:
public class Test  extends Component {
    BufferedImage speicherbares;
    BufferedImage biSrc;
    BufferedImage biDest;
    BufferedImage bi;
    Graphics big;
    int w;
    int h;

    public void loadImage()   throws Exception  {
        File scannerBild = new File("screen1.png");
        speicherbares = ImageIO.read(scannerBild);
        MediaTracker mt1 = new MediaTracker(this);
        mt1.addImage(speicherbares, 1);
        mt1.waitForAll();

        w = speicherbares.getWidth(this);
        h = speicherbares.getHeight(this);
        System.out.println("w: " + w + ", " + h);
    }

    public void createBufferedImages()  {
        biSrc = null;
        biDest = null;
        bi = null;

        biSrc = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

        big = biSrc.createGraphics();
        big.drawImage(speicherbares, 0, 0, this);

        biDest = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        bi = biSrc;
    }

    public static void main(String[] args)    throws Exception  {
        mem();

        Test t = new Test();
        t.loadImage();
        mem();
        for (int i = 0; i < 5; i++)  {
            t.createBufferedImages();
            mem();
        }
    }

    static void mem() {
        Runtime r = Runtime.getRuntime();
        long used = r.totalMemory() - r.freeMemory();
        long free = r.maxMemory() - used;
        System.out.println("used: " + used / 1000000 + ", free: " + free / 1000000);
    }
}
Ausgabe mit einer Beispieldatei und Standardspeicher von 66 MB:
Code:
used: 0, free: 66
w: 2560, 1992
used: 15, free: 50
used: 56, free: 9
used: 56, free: 10
used: 56, free: 10
used: 56, free: 10
used: 56, free: 10
ohne = null kommt es zur Memory-Exception, mit = null kann der GarbageCollector aufräumen,
man muss den auch nicht unbedingt bitten, bevor er eine so schwerwiegenden Fehler erzeugt
wird er doch wohl so gewissenhaft wie möglich nachschauen, oder gibt es irgendwo ein Codebeispiel dafür?

mit kleineren Bildern kann man testen was alles noch geht und was nicht,
der Code ist ja bisschen komplizierter, gleich zwei Images die auf null gesetzt werden, dazu noch ein Graphics-Objekt welches vielleicht das Raster des Bildes bzw. das Bild selber doch sicherlich referenziert
wahrscheinlich muss genug Luft für ein neues Bild sein, wenn das erzeugt wurde dann werden Bild 1 + Graphics des alten Bildes gelöscht, dann kann das zweite Image erstellt werden

gut möglich dass der restliche Code bei dir noch beliebig anderes interessantes enthält
 
Zuletzt bearbeitet von einem Moderator:

headnut

Gesperrter Benutzer
Fantastisch

Ich habe meinen Text gemäss deinen Angaben angepasst und alle Referenzen von Bildobjekten auf null gesetzt! Inklusiv mediatracke und Graphics

Code:
speicherbares = null;
    	
    	biSrc = null; 
    	biDest = null; 
    	bi = null;
    	temp = null;
    	big = null;

Und vorallem der graphics hat doch enorm viel gebracht!

Vielen Dank für die ausführungen es funktioniert nun einwandfrei!

Danke
 
S

SlaterB

Gast
hmm, big= null hatte ich selber gar nicht,
dann dürften in meinem Beispiel die 10 MB freier Speicher + die ca. 15 MB vom freigesetzten zweiten Bild reichen,
um das erste neu zu erzeugen, dann wird das erste überschrieben, auch Graphics, und es ist wieder Platz fürs zweite,
ok, ich kann wieder glauben wieso mein Programm funktioniert ;)
 
Zuletzt bearbeitet von einem Moderator:

Neue Themen


Oben