Warum frisst die VM hierbei meinen Speicher?

philippo

Mitglied
Erstmal sorry für diesen plakativen Titel...
Ich habe ein Mini-Programm geschrieben, das einfach nur eine Datei A ausliest und nach B schreibt. (Warum man sowas tut? :rolleyes: Besser nicht fragen bitte....)
Dieses soll Programm ununterbrochen laufen, daher die Schleife. 1x am Tag wird die Box neu gestartet. Das Problem ist, dass der Speicherbedarf der VM langsam aber sehr kontinuierlich ansteigt! Ich habe das jetzt 10 min. beobachtet: es begann bei 7,5 MB und benötigt inzwischen schon 9 MB.
Es wäre wirklich super, wenn mir irgendjemand sagen könnte, ob dieser Code hier ineffizient ist und was ich sonst noch alles falsch gemacht habe! Ich bin kein professioneller Entwickler, will aber wirklich gerne dazulernen.
Danke im Voraus.
Hier ist der Code:
Code:
import java.io.*;
import java.util.Properties;

public class FileSync {

	/**
	 * Dient der Realisierung einer Fileschnittstelle zwischen 2 MT-Instanzen 
	 * Kopiert kontinuierlich eine Datei von a nach b.
	 * 
	 * params:
	 * SyncPause
	 * FilenameFrom (abs. Pfad)
	 * FilenameTo (abs. Pfad)
	 * 
	 */
	
	public static void main(String[] args) {
		System.out.println("FileSync start");
		
		// StdErr in Datei umleiten		
    	try
        {
          java.io.FileOutputStream outstream = new java.io.FileOutputStream("FileSyncErr.log");
          System.setErr(new java.io.PrintStream(outstream));
          // System.setOut(new java.io.PrintStream(outstream));
        }
        catch(Exception e){        	
        	System.out.println("Logging in Datei umleiten schlug fehl.");
        	e.printStackTrace();
        }
        
    	// Properties-Datei auslesen        
    	File datei = new File("FileSync.properties");
    	Properties fileProp = new Properties(); 
    	
    	System.out.println("\nDefaults setzen");
		int SyncPause=500;
		String strFilenameFrom = "C:\\send.txt";
		String strFilenameTo = "C:\\receive.txt";
		System.out.println("SyncPause=" + SyncPause);
    	System.out.println("strFilenameFrom=" + strFilenameFrom);
    	System.out.println("strFilenameTo=" + strFilenameTo);
    	 
    	try {
    		FileInputStream stream = new FileInputStream(datei);    		    		
    		fileProp.load(stream);
    		
			SyncPause = Integer.parseInt(fileProp.getProperty("SyncPause"));
			strFilenameFrom = fileProp.getProperty("FilenameFrom");
			strFilenameTo = fileProp.getProperty("FilenameTo");
			
    		} 
    	catch (FileNotFoundException e) {
    			System.out.println("Properties-Datei auslesen: File Not Found "+datei.getAbsolutePath());
    			e.printStackTrace();
    		} 
    	catch (Exception e2) {    			
    			System.out.println("Properties-Datei auslesen: Unbekannter Fehler");
    			e2.printStackTrace();
    		}
    	System.out.println("\nProperties ausgelesen");
    	System.out.println("SyncPause=" + SyncPause);
    	System.out.println("strFilenameFrom=" + strFilenameFrom);
    	System.out.println("strFilenameTo=" + strFilenameTo);
    	
    	File FilenameFrom = new File(strFilenameFrom);
		File FilenameTo = new File(strFilenameTo);

        // Ende
	    while(true){
	    	copyFiles(FilenameFrom, FilenameTo);
	    	try {
	    		Thread.sleep(SyncPause);
	    		} catch (InterruptedException e){
	    			System.out.println("Thread.Sleep führte zu error");
	    			e.printStackTrace();
	    		// the VM doesn't want us to sleep anymore,
	    		// so get back to work
	    		}
	    }
	    }
	
	static void copyFiles(File FilenameFrom, File FilenameTo){
		System.out.println("sync " + System.currentTimeMillis() / 1000);
		// Datei kopieren 
		if(FilenameTo.exists()) {
			FilenameTo.delete();
		}
		
	    byte[] buffer = new byte[512];
	    int read = 0;
	    InputStream in = null;
	    OutputStream out = null;
	    try {
	        in = new FileInputStream(FilenameFrom);
	        out = new FileOutputStream(FilenameTo);
	        while(true) {
	            read = in.read(buffer);
	            if (read == -1) {
	                //-1 bedeutet EOF
	                break;
	            }
	            out.write(buffer, 0, read);
	        }
	    }
	    catch (Exception e){
	    	System.out.println("Fehler beim Kopieren");	    	
			e.printStackTrace();
	    }
	    finally {
	        // Sicherstellen, dass die Streams auch bei einem throw geschlossen werden.
	        // Falls in null ist, ist out auch null!
	        if (in != null) {
	        //Falls tatsächlich in.close() und out.close()
	        //Exceptions werfen, wird die jenige von 'out' geworfen.
	            try {
	                in.close();
	            }
	            catch (Exception e) {
	            	System.out.println("Fehler schließen eines Streams.");
	            	e.printStackTrace();
	            }
	            
	            if (out != null) {
                	try {
                		out.close();
                	}
                	catch (Exception e) {
                		System.out.println("Fehler schließen eines Streams.");
                		e.printStackTrace();
                	}
	                
	            }
	        }
	    }
	}
}
 
Hast du mal mit einem Profiler geguckt? Was ist wenn du testweise die copy Methode rausnimmst? Steigt dann dein Speicherverbrauch trotzdem noch an
 
Sorry, was ist denn ein Profiler?

Mir ist gestern noch was anderes eingefallen. Ich initialisiere das byte-Array zum kopieren ja mit 512 bytes. Die Zahl habe ich willkürlich gewählt, wie gesagt, ich bin kein professioneller Entwickler.... Kann der linear zunehmende Speicherverbrauch evtl. davon kommen?
 
...werden doch geschlossen!? Oder wie soll ich deine Frage verstehen?

Jedenfalls habe ich heute etwas über den Garbage Collector gelernt :)
Für den Speicherbedarf meines schönen Programms gibt es eine obere Grenze, für die der GC sorgt. Puh!
Außerdem initiiere ich das byte-Array jetzt mi 2 byte.
---> Erledigt.
 
Zurück