Threads RAM Problem

Kababär

Top Contributor
Hi,

ich will viele Bilder aus einem Internet laden und diese auf meine Festplatte speichern.
Allerdings habe ich das Problem, dass der Arbeitsspeicher langsam aber schnell voll wird.

jvm_entry_memory_leak.PNG

Ich benutze einen ThreadPoolExecutor, um mehrere Bilder gleichzeitig downloaden zu können.
Mein Verständnis vom TPE ist, dass man eine maximale Anzahl von Threads angeben kann, die zur gleichen Zeit arbeiten können. Beendete Threads werden entfernt.
Also habe ich das so implementiert

Code:
interpreteLines(list1, infos);
            interpreteLines(list2, infos);
            // ExecutorService executorService = Executors.newFixedThreadPool(MAX_THREADS);
            int corePoolSize = 5;
            int maxPoolSize = 10;
            long keepAliveTime = 20;
            ExecutorService executorService = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime,
                    TimeUnit.SECONDS, new LinkedBlockingQueue<>());
            for (int i = 0; i < infos.size(); i++) {
                Info inf = infos.get(i);
                if (!(inf.getUrl().toLowerCase().endsWith(".jpg") || inf.getUrl().toLowerCase().endsWith("jpeg"))) {
                    System.out.println(inf.getUrl() + " kein JP(E)G!");
                    continue;
                }
                DownloadRunner dr = new DownloadRunner(inf, i);
                executorService.execute(dr);
            }

            executorService.shutdown();
            while (!executorService.isTerminated()) {
            }
            System.out.println("\nAlles gedownloaded");

Ich öffne eine Textdatei, wo Informationen zu den Bildern gegeben sind. Diese lade ich über "interpreteLines". In der Schleife erstelle ich mir ein DownloadRunner, der das Bild von der URL (die im Info-Object "inf" steht) runterlädt und abschließend als BufferedImage auf die Festplatte schreibt. Danach wird das BufferedImage geflushed (mit flush()).
Geschrieben werden die Bilder über ImageIO.

Was ist hier falsch? Wie geht es richtig? Wie kriege ich den memory leak in den Griff?
Eine vergebliche Lösung war es, eine BlockingQueue zu definieren und diese an den TPE zu übergeben, statt einer neu initialisierten BQ. Dann in der Schleife die erstellen DownloaderRunner per "put(dr)" dem TPE anzureichern. Allerdings passiert dann gar nichts.

Wäre nett, wenn mir jemand helfen könnte.
 

mrBrown

Super-Moderator
Mitarbeiter
Bist du mal mit nem Profiler durchgegangen?

Hohe RAM-Auslastung muss in Java kein Memory-Leak bedeuten.
Kann auch einfach sein, das der GC noch nicht aufgeräumt hat, weil genug frei ist, oder das irgendwann mal so viel Speicher brauchte, der GC den aber freigeräumt hat und der intern leer ist.

Wenn du das begrenzen willst, kannst du die Maximale Größe des Heaps setzten - Standardmäßig müsste das auf 1/4 deines RAMs begrenzt sein
 

Kababär

Top Contributor
Ne mit einem Profiler habe ich noch nie gearbeitet.. hab den VisualVM ausprobiert und der hängt sich bei der Kalibrierung mit einem Prozess auf.
Ein Eclipse Plug-in (VirtualJava) hat Probleme bei der Darstellung. In den Properties wird nichts angezeigt.

Der RAM nur für das Java Programm hat irgendwann 1,8 GB in Anspruch genommen bei vorhandenen 4GB. Da habe ich dann abgebrochen..
Mich wundert es, weil ich so gut wie nur lokale Variablen verwende.
 

Kababär

Top Contributor
ok, ich stelle soeben fest, dass das Problem auch beim sequentiellen Laufen passiert.

Der Code sieht circa so aus

Code:
class DownloadRunner implements Runnable {

    private Info inf;

    private int taskID;

    public DownloadRunner(Info inf, int taskID) {
        this.inf = inf;
        this.taskID = taskID;
    }

    public void run() {
        System.out.println(taskID + "is running " + inf.getUrl());
        try {
            String name = inf.getName() + "_" + inf.getFace_id() + "_" + inf.getImage_id() + ".png";
            // URL url = new URL(inf.getUrl());

            BufferedImage bi = readBuffImg(inf.getUrl());// ImageIO.read(url);
            if (bi == null) {
                System.out.println("no image ...");
                return;
            }
            Rectangle rectangle = bboxToRect(inf.getBbox());
            if (rectangle == null) {
                System.out.println("no rectangle");
                return;
            }
            BufferedImage biCropped = cropImage(bi, rectangle);
            if (biCropped != null) {
                String root = Downloader.root;

                createDirIfNotExists(root + Downloader.dest);
                File file = new File(root + Downloader.dest + name);
                if (file.exists())
                    file.delete();
               // paar Operationen auf das Bild anwenden und dann schreiben
              // try-catches, end of class
 

JuKu

Top Contributor
Ich vermute mal, der wird das BufferedImage noch nicht freigegeben haben.
Das sind unkomprimiert Breite x Höhe x 4 Byte --> bei einem einzigen HD Bild (1920x1080 Pixel) 8.294.400 Byte (= 8MB) an Payload. Dazu kommt Overhead für das Array, die einzelnen Integers, die Referenzen, whatever...
Das klingt jetzt nach wenig, ist es aber eig. gar nicht. Bei 100 Bildern hast du über einem GB verbraucht.
Und die JVM selbst braucht auch ein wenig RAM. Und da der Garbage Collector (du erzeugst ja ne Menge GC Pressure) auch nicht dauerhaft läuft, wird er wie @mrBrown sagte, einfach noch nicht aufgeräumt haben.

Außerdem cacht ImageIO meines Wissens Daten --> da wird auch einiges an RAM drauf gehen.
 

JStein52

Top Contributor
Der RAM nur für das Java Programm hat irgendwann 1,8 GB in Anspruch genommen bei vorhandenen 4GB.
Wenn die Theorien zum GC stimmen und es wirklich kein Memory-Leak ist sollte ihn eine Verkleinerung des zur Verfügung stehenden Speichers auf sagen wir 1 GByte ja zum Aufräumen zwingen und es sollte nicht zu einer ...OutOfMemory-Exception kommen. Hast du das schon mal probiert ?
 

mrBrown

Super-Moderator
Mitarbeiter
Wenn die Theorien zum GC stimmen und es wirklich kein Memory-Leak ist sollte ihn eine Verkleinerung des zur Verfügung stehenden Speichers auf sagen wir 1 GByte ja zum Aufräumen zwingen und es sollte nicht zu einer ...OutOfMemory-Exception kommen. Hast du das schon mal probiert ?
OutOfMemoryException käme eh erst nach Freiräumen, die kann man nur mit mehr Speicher verhindern.
 

Kababär

Top Contributor
Nur so findet man von vorneherein schlechten Code.
Naja kommt auch ein bisschen aufs Gebiet an... wenn ich ein Programm für Flughäfen schreibe, darf die JVM doch bestimmt bisschen mehr als 512MB in Anspruch nehmen :D

Also das Programm pendelt sich so bei 1,8GB bis 1,9GB ein. Hab das Programm auch mittlerweile fertig laufen lassen.. hab mich nur über die gigantische Zahl erschreckt.. Das ist fast mehr in Anspruch genommener Platz als bei einem aktuellen Videospiel..
Nach jedem Aufruf der obigen Methode rufe ich allerdings auch explizit "System.gc()" auf. Dachte eig. das wäre ein Appell an die JVM aufzuräumen. Scheint wohl so zuverlässig wie "Thread.yield()" zu sein, auch wenn das zwei total unterschiedliche Konzepte sind.
 

Thallius

Top Contributor
Tja da frag ich mich was du vor 10 Jahren gemacht hättest als 1GB RAM Standard war. Heutzutage wird einfach inflationär mit Speicher und CPU Speed 7mgegang3n einfach weil es da ist. Ganz ehrlich: eine Software die 2GB Speicher braucht muss für mich eine 3D Echtzeit Simulation mit AR und Ki sein. Jede andere Software kann ich so schreib3n das sie mit 512MB locker auskommt.

Gruß

Claus
 

Thallius

Top Contributor
Ist ja auch keine Kunst, wird dann halt nur langsamer...

Quak, wofür braucht man 512MB am Stück? Das sind 512 bildschirmfüllende JPEGs oder 512.000 Musiktitel oder oder oder. Auf jeden Fall ein hundertfaches von dem was ein Mensch, der den Computer immer noch bedient, aufnehmen kann. Ergo vollkommen sinnlos das alles gleichzeitig im RAM zu halten.
 

Kababär

Top Contributor
Naja kommt eben ganz auf das Anwendungsgebiet. Ein einfacher Taschenrechner wird nicht so viel RAM benötigen wie eine Anwendung zur Hautkrebs- oder Tumorklassifikation.
Ich denke bei letzterem sind mehr als 512MB im RAM zu verkraften :D

Beim Machine Learning können ganz schnell mal eben die Kapazitäten privater Leistungsmaschinen aufgebraucht werden. Aber das ist ein anderes Thema.
Apropos, das eigentliche Thema ist zwar noch ungelöst, aber nicht mehr aktuell :oops:
 

mrBrown

Super-Moderator
Mitarbeiter
Nach jedem Aufruf der obigen Methode rufe ich allerdings auch explizit "System.gc()" auf. Dachte eig. das wäre ein Appell an die JVM aufzuräumen. Scheint wohl so zuverlässig wie "Thread.yield()" zu sein, auch wenn das zwei total unterschiedliche Konzepte sind.
Das ist nicht ohne Grund verpönt und richtet meist mehr schaden als Nutzen an;)

Quak, wofür braucht man 512MB am Stück? Das sind 512 bildschirmfüllende JPEGs oder 512.000 Musiktitel oder oder oder. Auf jeden Fall ein hundertfaches von dem was ein Mensch, der den Computer immer noch bedient, aufnehmen kann. Ergo vollkommen sinnlos das alles gleichzeitig im RAM zu halten.
Keine Ahnung was du für Musik hörst, aber ich bring in 512MB keine 100 Titel unter...

Ich find 512MB nicht sonderlich viel, n Programm darf durchaus mal mehr als 5% meines Speichers nutzen...
 

JStein52

Top Contributor
aber ich bring in 512MB keine 100 Titel unter.
Aber du kannst dir trotzdem immer nur einen anhören, oder eine begrenzte Anzahl von Bildern gleichzeitig anschauen.
n Programm darf durchaus mal mehr als 5% meines Speichers nutzen...
Ja weil du den grössten hast, du solltest aber bedenken dass dein Programm evtl. auch woanders laufen sollte ...
Und es deshalb durchaus sinnvoll ist sich über seinen Speicherverbrauch Gedanken zu machen. Und gerade du bist ja einer der an jedem Algorithmus noch ein paar Byte rausquetscht.
 

JuKu

Top Contributor
Nach jedem Aufruf der obigen Methode rufe ich allerdings auch explizit "System.gc()" auf. Dachte eig. das wäre ein Appell an die JVM aufzuräumen. Scheint wohl so zuverlässig wie "Thread.yield()" zu sein, auch wenn das zwei total unterschiedliche Konzepte sind.

Richtig! System.gc() schlägt der JVM lediglich vor, den GC aufzuräumen, erzwingt es aber nicht.
Letzendlich bestimmt die JVM immer noch selbst, wann der GC aktiv wird und wann nicht.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
krgewb Problem mit Umlauten und Eszett bei InputStream Allgemeine Java-Themen 3
Max246Sch Backtracking Problem Box Filler Allgemeine Java-Themen 6
NightVision402 VisualVM Startskript Problem Allgemeine Java-Themen 3
javaBoon86 Email Server Connection Problem Allgemeine Java-Themen 1
F Problem mit PDFBOX Library Allgemeine Java-Themen 1
A Java modul Problem Allgemeine Java-Themen 4
D Read JSON File Problem Allgemeine Java-Themen 9
urmelausdemeis Exception in thread "main" java.lang.Error: Unresolved compilation problem: Allgemeine Java-Themen 7
J Problem mit JasperReports Allgemeine Java-Themen 8
M log4j Problem mit jlink Allgemeine Java-Themen 19
8u3631984 Problem beim Mocken von Record Klassen Allgemeine Java-Themen 4
torresbig Website login Problem - Jsoup, wie bisher, klappt nicht! Allgemeine Java-Themen 31
P Selenium . getText Problem Allgemeine Java-Themen 9
A Jar zu Exe Problem Allgemeine Java-Themen 13
sserio Variablen Liste erstellt und ein Problem mit dem Index Allgemeine Java-Themen 6
S Folgendes Problem bei einem Programm Allgemeine Java-Themen 1
stormyark Problem beim Klassen erstellen Allgemeine Java-Themen 1
A Thread.sleep Problem Allgemeine Java-Themen 2
A Problem bei der Nachbarschafttest Allgemeine Java-Themen 11
Splayfer Problem: no main manifest attribute Allgemeine Java-Themen 3
G javamail Problem beim Empfangen von Nachrichten Allgemeine Java-Themen 3
Splayfer JDA Problem mit MessageCounter Allgemeine Java-Themen 0
Splayfer Problem mit BufferedWriter Allgemeine Java-Themen 3
F Streams als Alternative für dieses Problem ? Allgemeine Java-Themen 15
N Maven Problem mit Datenbanktreiber (H2 Embedded) Allgemeine Java-Themen 12
T Problem beim Umwandeln in eine Jar-Datei Allgemeine Java-Themen 3
B Einfach Elemente zweier Arraylisten kreuz und quer vergleichen, min und max Problem? Allgemeine Java-Themen 16
C ArrayList Problem Allgemeine Java-Themen 3
kev34 nim-Spiel problem Allgemeine Java-Themen 1
D Firebase retrieve data Problem, Child Element wird nicht angesprochen Allgemeine Java-Themen 0
G Welches Problem besteht bei den Typparametern? Allgemeine Java-Themen 5
temi Problem mit Aufrufreihenfolge bei Vererbung Allgemeine Java-Themen 3
Sumo_ow "ArrayIndexOutofBoundsException: 2" Array Problem Allgemeine Java-Themen 6
T PIM basierend auf netbeans via AnyDesk Problem Allgemeine Java-Themen 3
xGh0st2014 Problem mit Java Array Allgemeine Java-Themen 1
Kirby.exe Verständnis Problem bei Rucksack Problem Allgemeine Java-Themen 6
B Eclipse-Lombok-Problem Allgemeine Java-Themen 19
I Input/Output ObjectOutputStream - Problem Allgemeine Java-Themen 7
1 Multiple Choice Knapsack- Problem Allgemeine Java-Themen 2
kodela Problem mit strukturiertem Array Allgemeine Java-Themen 18
E Problem mit Gridlayout und Button Allgemeine Java-Themen 2
A Array Problem Allgemeine Java-Themen 8
bueseb84 Problem Allgemeine Java-Themen 0
S Problem mit Arrays Allgemeine Java-Themen 1
D Nullpointer Exception Problem Allgemeine Java-Themen 5
B Problem mit meinen Klassen Allgemeine Java-Themen 6
A HashMap Methode "get()"-Problem Allgemeine Java-Themen 28
J Problem beim Umstellen auf Java jdk 13 Allgemeine Java-Themen 3
J Problem bei Install java 13 Allgemeine Java-Themen 3
X Profitable Reise Problem Allgemeine Java-Themen 32
A Problem beim öffnen von Java-Installern Allgemeine Java-Themen 1
Dann07 Problem mit JavaMail API Allgemeine Java-Themen 26
J Problem beim Generischen Klassen und Interfaces Allgemeine Java-Themen 2
L Klassen Algorithmus für das folgende Problem entwickeln? Allgemeine Java-Themen 30
J Clear-Problem Allgemeine Java-Themen 10
B Problem zu einem Java Projekt Allgemeine Java-Themen 6
S JFileChooser Problem Allgemeine Java-Themen 4
M Traveling Salesman - MST Heuristik Problem Allgemeine Java-Themen 4
J Traveling Salesman Problem Allgemeine Java-Themen 14
E Java Editor Problem mit 2er Exceptions Allgemeine Java-Themen 12
C code oder Bibliotheken für 2-Center Problem Allgemeine Java-Themen 4
M Salesman Problem - Bruteforce Algorithmus Allgemeine Java-Themen 23
S Methoden Problem mit NullPointerException Allgemeine Java-Themen 9
Javafan02 Problem mit if-clause Allgemeine Java-Themen 17
J Lombok Problem mit Konstruktoren bei Verberbung Allgemeine Java-Themen 1
kodela Event Handling Problem mit der Alt-Taste Allgemeine Java-Themen 16
W Threads Problem Allgemeine Java-Themen 15
D (Verständnis-)Problem mit Unterklasse Allgemeine Java-Themen 4
S Problem mit Generic bei unmodifiableCollection Allgemeine Java-Themen 4
S jserialcomm Problem Allgemeine Java-Themen 1
Flynn Thread-Problem... Allgemeine Java-Themen 2
J Generische Interface - Problem Allgemeine Java-Themen 3
G Problem beim GUI Allgemeine Java-Themen 9
L Applet Problem "security: Trusted libraries list file not found" ? Allgemeine Java-Themen 7
A OOP Problem beim Berechnen der größten Fläche eines Ringes Allgemeine Java-Themen 19
T Problem mit externen Datenbankzugriff über SSH Tunnel Allgemeine Java-Themen 4
F Problem beim Einlesen einer Textdatei Allgemeine Java-Themen 12
S Java OpenOffice Problem mit Windows-Benutzerwechsel Allgemeine Java-Themen 19
P Operatoren Problem mit Zähler in recursiver Schleife Allgemeine Java-Themen 2
C Int Problem Allgemeine Java-Themen 8
C J2V8 NodeJs Java Bride Problem und Frage!?!? Allgemeine Java-Themen 1
J Problem bei Hashmap Key-Abfrage Allgemeine Java-Themen 4
C Webseiten Programm problem Allgemeine Java-Themen 5
M LocalDate Problem Allgemeine Java-Themen 4
J "Problem Objektorientierung" Allgemeine Java-Themen 20
geekex Problem Meldung! Was tun?! Allgemeine Java-Themen 19
T Klassen Override Problem Allgemeine Java-Themen 7
L Unbekanntes Problem Allgemeine Java-Themen 1
FrittenFritze Problem mit einer JComboBox, Event temporär deaktivieren Allgemeine Java-Themen 11
Blender3D Java Swing Programm Windows 10 Autostart Problem Allgemeine Java-Themen 2
F HTTPS Zertifikat Problem Allgemeine Java-Themen 3
M OpenCV KNearest Problem Allgemeine Java-Themen 0
Tommy Nightmare Project Euler: Problem 22 Allgemeine Java-Themen 2
C Abstrakte Klasse, lokale Variable-Problem Allgemeine Java-Themen 1
N Vererbung Design-Problem mit vorhandenen, von der Klasse unabhängigen Methoden Allgemeine Java-Themen 12
P Eclipse Projekt anlegen macht Problem Allgemeine Java-Themen 1
RalleYTN META-INF/services Problem Allgemeine Java-Themen 3
F Java Mail Problem: Authentifizierung wird nicht immer mitgeschickt Allgemeine Java-Themen 1
I Problem beim Aufrufen, von Objektmethoden/ -variablen Allgemeine Java-Themen 6
K Thread Problem Allgemeine Java-Themen 6

Ähnliche Java Themen

Neue Themen


Oben