1. Dashboard
  2. Forum
    1. Unerledigte Themen
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team-Mitglieder
    4. Trophäen
    5. Mitgliedersuche
  4. Tutorial Bereich
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Seiten
  • Forum
  • Lexikon
  • Erweiterte Suche
  1. Informatik Forum
  2. Webmaster & Internet
  3. Entwicklung

memory leaks - woher?

    • Frage
  • beat
  • 23. Dezember 2007 um 15:41
  • Unerledigt
  • beat
    14
    beat
    Mitglied
    Reaktionen
    2
    Punkte
    2.007
    Beiträge
    338
    • 23. Dezember 2007 um 15:41
    • #1

    hallo

    hab mir ein kleines tool geschrieben mit dem ich verzeichnisstrukturen auf ein anderes spiegeln kann, also ein backup des baums machen kann.

    Das Problem ist dass sich aus irgendeinem grund der inaktive physikalische speicher immer weiter aufbläst und am schluss ca. 80% der gesicherten datenmenge ausmacht. Bei einem backup von 1,5Gb werden 1,2GB speicher inaktiv und werden auch nach beenden des Programmes vom os (os x 10.5.1) auch nicht wieder freigegeben. WTF? Das einzige wie ich mir das erklären könnte sind nicht geschlossene Streams, aber die schliesse ich alle brav.

    Hat wer eine idee was das verursachen könnte?

    Klasse die files kopiert:

    Java
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    
    import javax.swing.JProgressBar;
    
    
    public class FileManager {
    
    
    	public FileManager() {
    
    
    	}
    
    
    	/*
    	 * Kopiert das File source nach dest
    	 */
    
    
    	public boolean copy(File _source, File _dest) throws IOException {
    
    
    		File source = _source;
    		File dest = _dest;
    
    
    		if (source.isFile()) {
    
    
    			FileInputStream fis = new FileInputStream(source);
    			FileOutputStream fos = new FileOutputStream(dest);
    
    
    			if (!dest.exists())
    				dest.createNewFile();
    
    
    			byte buffer[] = new byte[65536]; // reading 65K blocks
    
    
    			long pos = 0;
    			int bytesToWrite = 0;
    
    
    			while (dest.length() < source.length()) {
    
    
    				bytesToWrite = fis.read(buffer, 0, 65536);
    
    
    				fos.write(buffer, 0, bytesToWrite);
    				pos += bytesToWrite;
    			}
    
    
    			fis.close();
    			fos.close();
    
    
    			if (dest.length() == source.length())
    				return true;
    
    
    		}
    		return false;
    
    
    	}
    
    
    	/*
    	 * Kopiert das File source nach dest und handled eine Progressbar (0% -
    	 * 100%);
    	 */
    
    
    	public boolean copy(File _source, File _dest, JProgressBar progressBar)
    			throws IOException {
    
    
    		File source = _source;
    		File dest = _dest;
    
    
    		if (source.isFile()) {
    
    
    			FileInputStream fis = new FileInputStream(source);
    			FileOutputStream fos = new FileOutputStream(dest);
    
    
    			if (!dest.exists())
    				dest.createNewFile();
    
    
    			byte buffer[] = new byte[65536]; // reading 65K blocks
    
    
    			progressBar.setIndeterminate(false);
    			progressBar.setValue(0);
    
    
    			long pos = 0;
    			int bytesToWrite = 0;
    
    
    			int barValue = 0;
    
    
    			int barSteps = -1;
    
    
    			int steps = 1;
    
    			try {
    				steps = (int) (source.length() / 100);
    
    
    			} catch (ArithmeticException ae) {
    
    
    			}
    
    
    			while (dest.length() < source.length()) {
    
    
    				bytesToWrite = fis.read(buffer, 0, 65536);
    				barSteps += bytesToWrite;
    
    				if (barSteps >= steps) {
    					progressBar.setValue(++barValue);
    					barSteps = -1;
    				}
    
    
    				fos.write(buffer, 0, bytesToWrite);
    				pos += bytesToWrite;
    			}
    
    
    			fis.close();
    			fos.close();
    
    
    			if (dest.length() == source.length()) {
    				progressBar.setValue(100);
    				return true;
    			}
    
    
    		}
    
    
    		return false;
    
    
    	}
    
    
    }
    Alles anzeigen

    Klasse die rekursiv den verzeichnisbaum durchgeht

    Java
    import java.io.File;
    import java.io.IOException;
    
    
    public class Processor implements Runnable {
    
    
    	Thread runner = null;
    	FileManager fileman;
    
    
    	long speicherplatz = 0;
    	int totalFileAmount = 1;
    	int backUpped = 1;
    	int filesVisited = 0;
    	float pValue = 0;
    	float x = 0;
    
    
    	File root;
    	File mirror;
    
    
    	public Processor(File root, File mirror) {
    
    
    		fileman = new FileManager();
    
    
    		this.root = root;
    		this.mirror = mirror;
    
    
    		if (runner == null) {
    			runner = new Thread(this);
    			runner.start();
    		}
    	}
    
    
    	public void start(File dir) {
    
    
    		BackupGUI.appendTextArea(dir.getAbsolutePath());
    
    		File[] files = dir.listFiles();
    
    
    		String tmp;
    
    
    		if (files.length > 0) {
    
    
    			for (int i = 0; i < files.length; i++) {
    
    
    				if (files[i].isFile() && !files[i].isHidden())
    					filesVisited++;
    
    
    				x = 100f / totalFileAmount;
    
    
    				BackupGUI.progress.setValue(Math.round(x * filesVisited));
    
    
    				tmp = files[i].getAbsolutePath().substring(
    						root.getAbsolutePath().length());
    
    
    				// System.out.println("TPM: " + tmp);
    
    
    				if (!new File(mirror + File.separator + tmp).exists())
    					backupFile(tmp, files[i]);
    
    
    				if (new File(mirror + File.separator + tmp).exists())
    					if (files[i].lastModified() > new File(mirror
    							+ File.separator + tmp).lastModified())
    						backupFile(tmp, files[i]);
    
    
    				/*
    				 * Rekursiver Aufruf
    				 */
    
    
    				if (files[i].isDirectory() && files[i].canRead()
    						&& files[i].exists())
    					start(files[i]);
    
    
    			}
    		}
    
    
    	}
    
    
    	private void backupFile(String directoryName, File file) {
    
    
    		// System.out.println(mirror +
    		// directoryName.substring(0,directoryName.lastIndexOf(File.separator)));
    		// System.out.println(mirror + " <<< >>> " +
    		// directoryName.substring(0,directoryName.lastIndexOf(File.separator)));
    
    
    		String newFile = "";
    		File f = new File(mirror
    				+ directoryName.substring(0, directoryName
    						.lastIndexOf(File.separator)));
    		f.mkdirs();
    
    
    		newFile = f.getAbsolutePath() + File.separator + file.getName();
    
    
    		File tmp = new File(newFile);
    
    
    		try {
    
    
    			if (file.length() <= 2000000l)
    				fileman.copy(file, tmp);
    			else
    				fileman.copy(file, tmp, BackupGUI.fileProgress);
    
    
    			speicherplatz += file.length();
    
    			if (file.isFile() && !file.isHidden()) {
    				backUpped++;
    				BackupGUI.setCorruptTagCounter(backUpped);
    			}
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    
    	}
    
    
    	public void countFiles(File dir) {
    
    
    		File[] files = dir.listFiles();
    
    
    		if (files.length > 0) {
    
    
    			for (int i = 0; i < files.length; i++) {
    
    
    				if (files[i].isFile() && !files[i].isHidden())
    					totalFileAmount++;
    
    
    				if ((totalFileAmount % 10) == 0) {
    
    
    					BackupGUI.setSongCounter(totalFileAmount);
    
    
    				}
    
    
    				if (files[i].isDirectory() && files[i].canRead()
    						&& files[i].exists())
    					countFiles(files[i]);
    
    
    			}
    		}
    
    
    	}
    
    
    	public void run() {
    
    
    		long start = System.currentTimeMillis();
    
    
    		BackupGUI.progress.setIndeterminate(true);
    		countFiles(root);
    		BackupGUI.setSongCounter(totalFileAmount);
    		BackupGUI.progress.setIndeterminate(false);
    		x = ((float) totalFileAmount / (float) 100);
    		BackupGUI.progress.setValue(0);
    		start(root);
    
    
    		BackupGUI.fileProgress.setValue(0);
    		BackupGUI.progress.setValue(0);
    		BackupGUI.appendTextArea("Alle Daten wurden gesichert");
    
    
    		BackupGUI.appendTextArea("Benötigte Zeit: "
    				+ ((double) System.currentTimeMillis() - (double) start)
    				/ 1000d + " Sekunden");
    		BackupGUI.appendTextArea("Benötigter Speicherplatz: "
    				+ (speicherplatz / 1000000) + " Mb (" + speicherplatz
    				+ " Bytes)");
    	}
    }
    Alles anzeigen

    Visit: http://itunes.apple.com/de/artist/cbh-mobile/id338117761

  • Ringding
    11
    Ringding
    Mitglied
    Reaktionen
    12
    Punkte
    1.237
    Beiträge
    244
    • 23. Dezember 2007 um 16:01
    • #2

    Sowas nennt sich Cache und hat mit deinem Programm überhaupt nichts zu tun.

    Gratulation übrigens zur korrekten Verwendung der Code-Tags!

  • beat
    14
    beat
    Mitglied
    Reaktionen
    2
    Punkte
    2.007
    Beiträge
    338
    • 23. Dezember 2007 um 16:53
    • #3

    also das ist es sicher nicht, 1,2GB inaktiver ram der nicht mehr freigegeben wird ist einfach nicht normal. Was soll eigentlich der zweite satz?

    Visit: http://itunes.apple.com/de/artist/cbh-mobile/id338117761

  • Sandybutt
    8
    Sandybutt
    Mitglied
    Reaktionen
    4
    Punkte
    554
    Beiträge
    99
    • 23. Dezember 2007 um 17:12
    • #4

    Ein System.exit(0) an Ende des Programms sollte dein Problem beheben. Alternativ kannst du auch versuchen, herauszufinden, welcher Thread die VM am Beenden hindert - Meine Vermutung ist, dass du ein Swing-GUI mit einem JFrame verwendest, dessen Default-Close-Operation nicht auf dispose gesetzt ist.

    "I don't think that Debian can really compete with Gentoo. Sure it might be okay, but when it comes to dependencies, you probably are still going to have to get them all on your own. Or is there something like portage in the Debian world as well?"

  • beat
    14
    beat
    Mitglied
    Reaktionen
    2
    Punkte
    2.007
    Beiträge
    338
    • 23. Dezember 2007 um 17:17
    • #5

    die gui macht ein EXIT_ON_CLOSE <=> System.exit(0)

    es gibt nur den einen Thread in der Processor Klasse und der läuft auch korrekt aus.

    Visit: http://itunes.apple.com/de/artist/cbh-mobile/id338117761

  • Sandybutt
    8
    Sandybutt
    Mitglied
    Reaktionen
    4
    Punkte
    554
    Beiträge
    99
    • 23. Dezember 2007 um 17:50
    • #6

    Seltsam. Der Speicher wird ja von der VM angefordert und ein System.exit beendet die VM in (fast) jedem Fall, also sollte der Speicher damit auch wieder freigegeben worden sein. Wie heißt denn der Prozess, der den Speicher angefordert hat? Evtl könntest du es doch noch mit einem explizitem System.exit versuchen?

    "I don't think that Debian can really compete with Gentoo. Sure it might be okay, but when it comes to dependencies, you probably are still going to have to get them all on your own. Or is there something like portage in the Debian world as well?"

  • Kampi
    27
    Kampi
    Mitglied
    Reaktionen
    193
    Punkte
    7.828
    Beiträge
    1.468
    • 23. Dezember 2007 um 19:48
    • #7
    Zitat von beat


    hab mir ein kleines tool geschrieben mit dem ich verzeichnisstrukturen auf ein anderes spiegeln kann, also ein backup des baums machen kann.

    habe ich das richtig verstanden? du hast nach rund 35 jahren "cp" neu in java erfunden? :winking_face: was kommt als naechstes? ein java-tool mit dem man verzeichnisse anlegen kann? ned boes gemeint :engel:

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 23. Dezember 2007 um 19:54
    • #8

    Also Deinen Code habe ich nicht so genau angeschaut, aber wenn Du Verzeichnisse direkt kopieren möchtest, verwende doch einfach FileUtils#copyDirectory aus dem Apache Commons Projekt.

    http://commons.apache.org/io/api-release…20java.io.File)

    Was Dein MemoryLeak betrifft, rate ich dir folgendes: Versuche Den State deiner Objekte erstens klein zu halten und zweitens zu kapseln. Du greifst z.B. in Deinem Code oefters auf statische Attribute zu und veraenderst diese (z.b. all die Aufrufe auf BackupGUI). Das macht Deinen Code

    - nicht threadsafe, weil mehrere Threads in beliebiger Reihenfolge Werte veraendern koennen.

    - schwer ueberschaubar, weil man mitdenken muss, wie der Zustand von BackupGUI gerade ist.

    - anfaellig fuer Memoryleaks, weil der globale state nicht unbedingt geloescht wird.

    Das Du eine statische Methode BackupGUI.appendTextArea hast, laesst mich darauf schliessen, das Du auch eine statische TextArea hast. Schau dir am besten mal einfach an wie andere Swing GUIs schreiben, dann siehst Du wie es auch anders geht.

    Ich empfehle dir deine Software so zu designen, dass

    - du moeglichst wenig Methoden mit Seiteneffekten hast.

    - deine Objekte so wenig wie moeglich von einander wissen muessen.

    - deine Objekte nur den kleinstmoeglichen Zustand besitzen. Also im Prinzip so wenig Instanz und Klassenvariablen wie nur moeglich. Aussnahmen sind statische, final Variablen. Wenn Du Instanzvariablen hast, dann deklariere sie wenn moeglich als final.

    Dann entstehen naemlich solche Memoryleaks erst gar nicht. Und wenn doch, dann sind die schnell gefunden.

    PS: Von System.exit() sollte man wenn moeglich ganz die Finger lassen.

    lg, Benjamin Ferrari, bookworm.at

  • beat
    14
    beat
    Mitglied
    Reaktionen
    2
    Punkte
    2.007
    Beiträge
    338
    • 23. Dezember 2007 um 19:54
    • #9

    is nicht wie copy. er kopiert nur dateien, dies noch nicht gibt bzw überschreibt ältere datei versionen mit neueren... ausserdem hab ich guis lieber. Will dann noch was einbauen dass ich ihm n verzeichnisse geb die er mir dann alle in einem backup verzeichnis sonstwo sichert.

    Visit: http://itunes.apple.com/de/artist/cbh-mobile/id338117761

  • mdk
    26
    mdk
    Emeritus
    Reaktionen
    130
    Punkte
    7.120
    Beiträge
    1.390
    • 23. Dezember 2007 um 19:58
    • #10
    Zitat von beat

    is nicht wie copy. er kopiert nur dateien, dies noch nicht gibt bzw überschreibt ältere datei versionen mit neueren...

    Also sowas wie cp -u?

  • beat
    14
    beat
    Mitglied
    Reaktionen
    2
    Punkte
    2.007
    Beiträge
    338
    • 23. Dezember 2007 um 20:02
    • #11

    es is so wie ich es implementiert hab und haben will :winking_face: nur eben mit memory leaks deren ursache ich net find.

    Visit: http://itunes.apple.com/de/artist/cbh-mobile/id338117761

  • mdk
    26
    mdk
    Emeritus
    Reaktionen
    130
    Punkte
    7.120
    Beiträge
    1.390
    • 23. Dezember 2007 um 20:09
    • #12
    Zitat von beat

    es is so wie ich es implementiert hab und haben will :winking_face: nur eben mit memory leaks deren ursache ich net find.

    Warum nimmst du nicht einfach ein Tool, das die selbe Funktionalität zur Verfügung stellt, sich seit mehreren Jahrzehnten bewährt hat und (recht) sicher keine memory leaks hat?

    Lesetipp: http://en.wikipedia.org/wiki/Not_Invented_Here

  • beat
    14
    beat
    Mitglied
    Reaktionen
    2
    Punkte
    2.007
    Beiträge
    338
    • 23. Dezember 2007 um 20:16
    • #13

    In dem thread gehts nicht um Not invented yet philosophien sondern um was anderes. Kann mir scho vorstellen dass ich die funktionalität auch mit cp hab, ich hab aber in meins schon zeit investiert und deswegen will ichs auch verwenden, was is so schwer daran zu verstehen.

    Visit: http://itunes.apple.com/de/artist/cbh-mobile/id338117761

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 23. Dezember 2007 um 20:34
    • #14
    Zitat von mdk

    Warum nimmst du nicht einfach ein Tool


    Lasst den armen Beat doch sein Programm schreiben wenn er das will. Etwas Uebung hat noch niemanden geschadet(*).

    (*) Naja meistens jedenfalls. Hat sich sicher schon mal ein Shaolin Moench beim Ueben mit einem Nunchaku die Ruebe eingeschlagen. Aber selbst der hat dabei wahrscheinlich noch was gelernt.

    lg, Benjamin Ferrari, bookworm.at

  • sauzachn
    17
    sauzachn
    Mitglied
    Reaktionen
    51
    Punkte
    3.101
    Beiträge
    606
    • 23. Dezember 2007 um 20:49
    • #15
    Zitat von beat

    Kann mir scho vorstellen dass ich die funktionalität auch mit cp hab, ich hab aber in meins schon zeit investiert und deswegen will ichs auch verwenden, was is so schwer daran zu verstehen.


    Du wirst mal ein exzellenter Softwareentwickler der alten Schule.

    Dipper dipper dii dipper dii dipper dii duuu

  • beat
    14
    beat
    Mitglied
    Reaktionen
    2
    Punkte
    2.007
    Beiträge
    338
    • 23. Dezember 2007 um 20:53
    • #16
    Zitat von sauzachn

    Du wirst mal ein exzellenter Softwareentwickler der alten Schule.

    Danke für deinen lösungsansatz

    Visit: http://itunes.apple.com/de/artist/cbh-mobile/id338117761

  • Kampi
    27
    Kampi
    Mitglied
    Reaktionen
    193
    Punkte
    7.828
    Beiträge
    1.468
    • 23. Dezember 2007 um 20:54
    • #17
    Zitat von sauzachn

    Du wirst mal ein exzellenter Softwareentwickler der alten Schule.


    hehe, so neumodernes hexenzeug wie "extreme programming" fangen wir uns gar nicht erst an. wenn schon zeit in ein projekt geflossen ist, dann ziehn wir das auch durch! :winking_face:

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

  • Sandybutt
    8
    Sandybutt
    Mitglied
    Reaktionen
    4
    Punkte
    554
    Beiträge
    99
    • 23. Dezember 2007 um 21:11
    • #18

    Vielleicht kannst du ja einmal den ganzen Code inklusive GUI posten, dann könnte mans auch nachvollziehen.

    Und zu den restlichen Kommentaren kann man nur sagen, dass durch das Verwenden von cp noch keiner gescheiter geworden ist (Macht sich auch in der Relevanz des Kommentarinhalts bemerkbar).

    "I don't think that Debian can really compete with Gentoo. Sure it might be okay, but when it comes to dependencies, you probably are still going to have to get them all on your own. Or is there something like portage in the Debian world as well?"

  • Ringding
    11
    Ringding
    Mitglied
    Reaktionen
    12
    Punkte
    1.237
    Beiträge
    244
    • 23. Dezember 2007 um 22:09
    • #19

    Ist doch völlig egal, warum er das will. So wie ich es verstanden habe, geht es hier nicht um ein Java memory leak, sondern er wundert sich einfach, dass nach der Beendigung des Programms der ganze Krempel, den er kopiert hat, im Cache liegt und daher notwendigerweise weniger Speicher frei ist als vorher. Das scheint ihn aus irgendeinem Grund zu stören. Aber da er sich ja so sicher ist, dass das nicht normal ist, habe ich auch keine Lust, ihm zu erklären, dass es das sehr wohl ist.

  • beat
    14
    beat
    Mitglied
    Reaktionen
    2
    Punkte
    2.007
    Beiträge
    338
    • 23. Dezember 2007 um 22:26
    • #20
    Zitat


    Aber da er sich ja so sicher ist, dass das nicht normal ist, habe ich auch keine Lust, ihm zu erklären, dass es das sehr wohl ist.

    Ich seh sowas nur zum ersten mal. Ich hatte erst letztens ein programm laufen dass mir 350GB Daten (~80000) files verarbeitet hat und das hat den inaktiven speicher überhaupt nicht aufgefüllt.

    Hier mal ein vorher und ein nachher bild von der aktivitätsanzeige. Der blaue inaktive teil der torte wird übrigends erst wieder freigegeben nachdem ich neu starte. Also normal kommt mir das nicht vor.

    Der Inhalt kann nicht angezeigt werden, da er nicht mehr verfügbar ist.

    Der Inhalt kann nicht angezeigt werden, da er nicht mehr verfügbar ist.

    Visit: http://itunes.apple.com/de/artist/cbh-mobile/id338117761

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Benutzer online in diesem Thema

  • 1 Besucher

Rechtliches

Impressum

Datenschutzerklärung