Binäruhr lädt Arbeitspeicher voll

timestamp

Mitglied Käsekuchen
Hallo allerseits,

ich habe mir aus Jux und Dollerei mal eine kleine Binäruhr geschrieben. Ein Blick in den Taskmanager zeigte mir aber, dass die Spalte "Arbeitsspeicher" sich etwa alle 2Sekunden um 4kB erhöht. Ich weiß nur nicht woran das liegt? Ich habe schon versucht alle Variablen vorher zu deklarieren, aber irgendwo habe ich wohl was übersehen (kenne mich mit der Speicherverwaltung von Java ohnehin gar nicht aus).

Hier der Code:
Java:
public class BinaryClock extends JFrame{
	JPanel contentPane;
	int i, h, m,s,pow,width,height;
	Calendar c;
	public BinaryClock(){		
		super("BinaryClock");
		setUndecorated(true);
		width = 140;
		height = 65;
		setBounds(1400, 50, width, height);
		setDefaultCloseOperation(EXIT_ON_CLOSE);	
		setResizable(false);		
		//AWTUtilities.setWindowOpaque(this, false);
		contentPane = new JPanel () {			
            protected void paintComponent(final Graphics  g) {
            	g.setColor(Color.white);
            	g.fillRect(0, 0, width, height);
            	g.setColor(Color.black);
            	g.drawRect(0,0,width-1,height-1);
            	c = Calendar.getInstance();
            	h = c.get(Calendar.HOUR_OF_DAY);            	            	
            	m = c.get(Calendar.MINUTE);
            	s = c.get(Calendar.SECOND);            	            	
            	
            	for( i = 0; i <= 5; i++ ){            		
            		pow = (int)Math.pow(2,i);            		
            		g.setColor(Color.black);
            		if( i < 5 ){            	            			
            			g.drawRect(110-i*20-1, 44, 16, 16);
            		}
            		g.drawRect(110-i*20-1, 24, 16, 16);
            		g.drawRect(110-i*20-1, 4, 16, 16);
            		g.setColor(Color.blue);
            		if( (h&pow) > 0 ){
            			g.fillRect(110-i*20, 45, 15, 15);
            		}
            		if( (m&pow) > 0 ){
            			g.fillRect(110-i*20, 25, 15, 15);
            		}
            		if( (s&pow) > 0 ){
            			g.fillRect(110-i*20, 5, 15, 15);
            		}
            		
            	}            	
            }
        };
        setContentPane(contentPane);               
        setAlwaysOnTop(true);		
        setVisible(true);     
        run();
	}	
	
	public void run(){
		while( true ){
			contentPane.repaint();
			try{
				Thread.sleep(1000);
			}
			catch(Exception e){}
		}
	}
	public static void main(String[] args){
		new BinaryClock();
	}
}
 
Hallo,

Ich hab mal deinen Code kopiert und ausgeführt, aber bei mir ändert sich nichts an der RAM Nutzung.
Zusätzlich hab ich mal die Verzögerung von 1000 ms auf 10 runter, damit's schneller geht, aber auch da hat sich nichts an der RAM Nutzung geändert.

Du kannst ja mal folgendes probieren:
Java:
public void run(){
        while( true ){
            contentPane.repaint();
            try{
                Thread.sleep(1000);
            }
            catch(Exception e){}
            System.gc();
        }
    }

Mit dem System.gc() rufst du den Garbage Collector auf, der mal schauen soll ob irgendwelche unnützige Objecte rumirren, wenn er solche findet, löscht er sie und gibt den RAM wieder frei.
Aber da dein Code eigentlich kaum Objekte anderer Klassen verwendet, bezweiflich ich fast, dass es was nützen wird.
Probier's einfach mal aus :)
 
Hi,
ich hab deinen Code mal ein wenig überarbeitet. Da mir aufgefallen ist, dass deine Variablen einen sehr großen Skope haben. Dadurch werden diese natürlich auch nicht vom GC gelöscht.

Zudem solltest du das neuzeichnen deiner GUI immer in einen Thread auslagern, da es sonst zu komplikationen kommen kann.

Außerdem ist mir in deiner Paint-Methode aufgefallen, dass du als allererstes den Hintergrund überzeichnest (damit der leer wird). Das ist aber gar nicht notwendig, wenn du am Anfang der Methode "super.paintComponent(g);" aufrufst. Diese Methode macht genau das.

Die Größe deines Fensters musst du auch nicht in Variablen zwischenspeichern, da du in der Paint-Methode über die ClipBounds darauf zugreifen kannst.
Java:
public class BinaryClock extends JFrame implements Runnable
{
	private final JPanel contentPane;
	
	public BinaryClock() {
		super("BinaryClock");
		setUndecorated(true);
		setSize(140, 65);
		setLocation(1400, 50);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setResizable(false);
		setAlwaysOnTop(true);
		contentPane = new JPanel()
		{
			private final Calendar c = GregorianCalendar.getInstance();
			
			@Override
			protected void paintComponent(final Graphics g) {
				super.paintComponent(g);
				final Rectangle clipBounds = g.getClipBounds();
				final int width = clipBounds.width;
				final int height = clipBounds.height;
				
				g.setColor(Color.black);
				g.drawRect(0, 0, width - 1, height - 1);
				
				c.setTimeInMillis(System.currentTimeMillis());
				final int h = c.get(Calendar.HOUR_OF_DAY);
				final int m = c.get(Calendar.MINUTE);
				final int s = c.get(Calendar.SECOND);
				
				for(int i = 0; i <= 5; i++) {
					final int pow = (int) Math.pow(2, i);
					g.setColor(Color.black);
					if(i < 5) {
						g.drawRect(110 - i * 20 - 1, 44, 16, 16);
					}
					g.drawRect(110 - i * 20 - 1, 24, 16, 16);
					g.drawRect(110 - i * 20 - 1, 4, 16, 16);
					g.setColor(Color.blue);
					if((h & pow) > 0) {
						g.fillRect(110 - i * 20, 45, 15, 15);
					}
					if((m & pow) > 0) {
						g.fillRect(110 - i * 20, 25, 15, 15);
					}
					if((s & pow) > 0) {
						g.fillRect(110 - i * 20, 5, 15, 15);
					}
				}
			}
		};
		add(contentPane);
		
		final Thread t = new Thread(this, "BinaryClock");
		t.setDaemon(true);
		t.start();
		
		setVisible(true);
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run() {
		try {
			while(true) {
				SwingUtilities.invokeAndWait(new Runnable()
				{
					@Override
					public void run() {
						contentPane.repaint();
					}
				});
				Thread.sleep(100);
			}
		} catch(final InterruptedException e) {
			e.printStackTrace();
		} catch(final InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(final String[] args) {
		new BinaryClock();
	}
}

Gruß

Fabio
 
Hi,

zur Behebung und Analyse von Memory-Leaks bin ich mit dem Programm VisualVM sehr zufrieden, ist ab dem JDK 6 auch standardmäßig bei Java dabei.

Grüße,
BK
 
Danke für deine Antwort Fabio.
Der Quelltext oben ist schon in soweit modifiziert, dass ich versucht habe das Problem zu lösen (deswegen der riesige Scope und das verzichten auf so viele Methoden wie möglich).
Anyways:
Dein Code erzeugt bei mir bis jetzt den stärksten Anstieg in der Arbeitsspeicherzeile.

So langsam glaube ich, dass mein Laptop und nicht mein Programm dafür verantwortlich ist.
Ich nutze:
-Windows 7 Home Premium SP1 (64bit)
-Radeon AMD A6-3410MX APU HD Graphics 1.60GHz
-4GB RAM

Ich habe das Programm sowohl über Eclipse, RunnableJar als auch direkt über die Konsole gestartet, aber bei allen 3 Startvorgängen kann ich den Anstieg beobachten.


Bratkartoffel: Ich habe mir das Programm einmal angesehen, leider kann ich mit den Daten dort nicht viel anfangen. Hier ein Screenshot von dem Programm
 
Ich kann die Beobachtung von Bratkartoffel bestätigen. Grund dafür ist, dass beim Zeichnen offensichtlich immer wieder neue Graphics-Objekte erzeugt werden.
 
Zurück