Frage zu Speicherverbrauch von Java-Applikation

Angiii

Erfahrenes Mitglied
Hallo,

ich erstelle gerade eine Java-Application die viele GUI-Elemtente (eine JTabbedPane, Buttons, Sliders) enthält. Wenn ich das ganze ausführe werden laut TastManager ca. 40MB Speicher von der Applikation belegt. Mir kommt das nach ganz schön viel vor, so riesig ist das Programm ja auch nicht. Teilweise steigt der Bedarf mit der Zeit auch noch leicht an!

Was kann ich da machen? Mein erster Gedanke, ich instanziere viele Klassen die ich dann nur kurz brauche. Die belegen ja dann weiterhin Speicher obwohl sie gar nicht mehr angesprochen werden. Oder erledigt das der Garabage Collector bereits für mich?

Und auch solche Konstrukte in meinem Code gefallen mir nicht:
Code:
for (int  i = 5; i<37; i++){
	//....			
	serial.sendCommand(i, 0xFF, 5, 5);
	new guiUpdate(serial.receivebuf) ;
       //....

}
In dieser Schleife rufe ich ständig die Klasse "guiUpdate" neu auf. Ist das in Ordnung so oder ist das im Bezug auf Perfomance eher schlecht?

Gibts ein paar Tips und Tricks um schöne schlanke Programme zu bekommen?
Danke schonmal. Ich denke das Thema wird auch für andere Leute interssant sein.
 
1. Der GarbageCollector räumt automatisch alles auf was nicht mehr referenziert wird. Das Aufräumen ist nicht immer sofort wenn keine Referenz mehr vorhanden ist. Aber das Aufräumen benötigt auch Performance.

2. Code Konventionen: Gewöhne dir an, z.B. Klassennamen groß zu schreiben. Schau dir die Code Convention von Sun als Richtlinie an.

3.
Mit
Java:
new guiUpdate(serial.receivebuf) ;
wird jedes Mal ein neues Objekt instantiiert was nachdem es nicht mehr benutzt wird aufgeräumt werden muss. Das neu Anlegen und Aufräumen frisst auch Performance.

Aktuell frage ich mich eher was diese Schleife und die Klasse guiUpdate macht :confused:
 
Ok, anscheinend frisst hier ja alles Performance. Hier mal bißchen mehr Erklärung zu meinem Code: Mein GUI stellt eine Art Fernsteueung für das Messgerät dar. Bei der for-Schleife handelt es um einen Aussschnitt aus einer Funktion, die von dem Messgerät die aktuellen Einstellungswerte ausließt. Die Klasse "guiUpdate" (ich frag mich wieso das die einzige Klasse ist die ich klieingeschrieben hab) aktualisiert dann das Applet auf Grund der zurückgegebenen Werte.

Hier ein Auszug aus dem Code:

Code:
public class guiUpdate implements MainInterface {
	public guiUpdate (byte [] source){
		
                if (source[2] == 0x0A){
 			getBrightness.setValue(source[3]);
 		}
		
		else if (source[2] == 0x0B) {
			getContrast().setValue(source[3]);
		}

               // .......

}

Meine for-Schleife schickt somit nacheinander verschiedene Befehle ans Gerät und aktualisiert dann auf Grund der zurückgegeben Werte über guiUpdate das GUI.
 
Ich würde das auf keinen Fall im Konstruktor machen. Es müsste doch möglich sein, einmal ein Objekt zu erstellen und das als Methode umzusetzen. Das würde schon viel verbessern.
 
Ich würde das auf keinen Fall im Konstruktor machen. Es müsste doch möglich sein, einmal ein Objekt zu erstellen und das als Methode umzusetzen. Das würde schon viel verbessern.

Ok, verstehe was du meinst. So wies jetzt ist wird ja die Klasse immer neu erstellt. Ich erstell das jetzt mal neu ohne das ich das ganze in den Konstruktor packe. Die Klasse sollte dann nur noch einmal initialisiert werden.

Was mich aber wundert: Die for-Scheife wird in meinem Programm erst gestartet, wenn ich mich mit Hilfe eines "Connect"-Buttons mit dem Messgerät verbunden habe. Vorher wird da nichts aufgerufen. Aber bereits in diesem Ruhezustand verbratet die Application schon ca. 33 MB Speicher für gar nix. Kann ich da an den Steuerelementen etwas machen?

Gibt es einen Unterschied ob ich die Steuerelemente mit der Konstante oder der Methode aufrufe? Ich hab z.B.:
Code:
public JButton connect = null;

public JButton getConnect() {
		if (connect == null) {
			connect = new JButton();
			// ....	
		}
		return connect;
}
Welcher Aufruf ist besser?
connect.setText("neuer Text"); oder getConnect().setText("nochmal");? Gut, an meinem hohen Speicherverbrauch tut das wahrscheinlich nichts zur Sache, aber interssieren würds mich dann doch.
 
Hallo,

du musst beachten das auch die JVM an sich schon einiges an Speicher belegt. Selbst kleinste GUI - Apps brauchen schon 20-24MB (je nach VM usw.)

Wenn du aber mal genau gucken willst was genau deinen Speicher belegt dann guck dir das ganze doch mal mit einem Profiler an (Bsp. JProfiler: http://www.ej-technologies.com/products/jprofiler/overview.html?gclid=CMSKp8mpj5wCFYYVzAodVXbqnA).
Das ganze ist eigentlich ziemlich einfach und du findest Speicher- und Performancefresser ziemlich einfach.

Hoffe ich konnte ein bisschen helfen.

Gruß
sony2
 
Ok, verstehe was du meinst. So wies jetzt ist wird ja die Klasse immer neu erstellt. Ich erstell das jetzt mal neu ohne das ich das ganze in den Konstruktor packe. Die Klasse sollte dann nur noch einmal initialisiert werden.

Was mich aber wundert: Die for-Scheife wird in meinem Programm erst gestartet, wenn ich mich mit Hilfe eines "Connect"-Buttons mit dem Messgerät verbunden habe. Vorher wird da nichts aufgerufen. Aber bereits in diesem Ruhezustand verbratet die Application schon ca. 33 MB Speicher für gar nix. Kann ich da an den Steuerelementen etwas machen?

Gibt es einen Unterschied ob ich die Steuerelemente mit der Konstante oder der Methode aufrufe? Ich hab z.B.:
Code:
public JButton connect = null;

public JButton getConnect() {
		if (connect == null) {
			connect = new JButton();
			// ....	
		}
		return connect;
}
Welcher Aufruf ist besser?
connect.setText("neuer Text"); oder getConnect().setText("nochmal");? Gut, an meinem hohen Speicherverbrauch tut das wahrscheinlich nichts zur Sache, aber interssieren würds mich dann doch.
Du machst im Constructor
Code:
connect = new JButton();

und greifst dann über connect.setText( ... ) drauf zu.

Wenn du eine Methode getConnectButton haben möchtest, dann gibt die nur noch "connect" zurück
Code:
 JButton getConnectButton() {
    return connect;
 }
 
Hallo,

du musst beachten das auch die JVM an sich schon einiges an Speicher belegt. Selbst kleinste GUI - Apps brauchen schon 20-24MB (je nach VM usw.)

Wenn du aber mal genau gucken willst was genau deinen Speicher belegt dann guck dir das ganze doch mal mit einem Profiler an (Bsp. JProfiler: http://www.ej-technologies.com/products/jprofiler/overview.html?gclid=CMSKp8mpj5wCFYYVzAodVXbqnA).
Das ganze ist eigentlich ziemlich einfach und du findest Speicher- und Performancefresser ziemlich einfach.

Hoffe ich konnte ein bisschen helfen.

Gruß
sony2

JProfiler ist ja wirklich mal eine feine Sache. Hab zumindest schonmal rausgefunden wieso mein Speicherverbrauch immer mehr wird (manche Threads werden bei bestimmten Handlungen einfach nochmal gestartet...). Im Anhang mal ein Screenshot der Speicherübersicht. Wer hätte das gedacht, String und Char sind sehr hungrige Gesellen. Aber wie (wenn überhaupt) kann ich die schlanker machen?
 

Anhänge

  • jprofiler.jpg
    jprofiler.jpg
    56,1 KB · Aufrufe: 63
Am besten finde ich am Anfang die Hotspot Ansicht im JProfiler.

Aber du solltest dir denke ich mal sowas wie Effective Java durchlesen. Wenn man ordentlich programmiert treten solche Probleme eigentlich nicht auf.
 
Am besten finde ich am Anfang die Hotspot Ansicht im JProfiler.

Aber du solltest dir denke ich mal sowas wie Effective Java durchlesen. Wenn man ordentlich programmiert treten solche Probleme eigentlich nicht auf.

Richtig gut ist auch die Threadansicht. Bin jetzt schon von 40MB auf 30MB Speicherverbrauch runter. Da geht doch noch was.....
 

Neue Beiträge

Zurück